diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 3610c759e..457180fdf 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -282,8 +282,20 @@ SET(repositories repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_entries_repository.h repositories/base/base_player_titlesets_repository.h + repositories/base/base_player_event_aa_purchase_repository.h + repositories/base/base_player_event_killed_npc_repository.h + repositories/base/base_player_event_killed_named_npc_repository.h + repositories/base/base_player_event_killed_raid_npc_repository.h repositories/base/base_player_event_log_settings_repository.h repositories/base/base_player_event_logs_repository.h + repositories/base/base_player_event_loot_items_repository.h + repositories/base/base_player_event_merchant_purchase_repository.h + repositories/base/base_player_event_merchant_sell_repository.h + repositories/base/base_player_event_npc_handin_repository.h + repositories/base/base_player_event_npc_handin_entries_repository.h + repositories/base/base_player_event_speech_repository.h + repositories/base/base_player_event_trade_repository.h + repositories/base/base_player_event_trade_entries_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h repositories/base/base_raid_members_repository.h @@ -467,8 +479,20 @@ SET(repositories repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_entries_repository.h repositories/player_titlesets_repository.h + repositories/player_event_aa_purchase_repository.h + repositories/player_event_killed_npc_repository.h + repositories/player_event_killed_named_npc_repository.h + repositories/player_event_killed_raid_npc_repository.h repositories/player_event_log_settings_repository.h repositories/player_event_logs_repository.h + repositories/player_event_loot_items_repository.h + repositories/player_event_merchant_purchase_repository.h + repositories/player_event_merchant_sell_repository.h + repositories/player_event_npc_handin_repository.h + repositories/player_event_npc_handin_entries_repository.h + repositories/player_event_speech_repository.h + repositories/player_event_trade_repository.h + repositories/player_event_trade_entries_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h repositories/raid_members_repository.h diff --git a/common/database.cpp b/common/database.cpp index f1d3a3757..4035ced31 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2155,18 +2155,18 @@ void Database::PurgeCharacterParcels() pel.event_type_name = PlayerEvent::EventName[pel.event_type_id]; std::stringstream ss; for (auto const &r: results) { - pd.from_name = r.from_name; - pd.item_id = r.item_id; - pd.aug_slot_1 = r.aug_slot_1; - pd.aug_slot_2 = r.aug_slot_2; - pd.aug_slot_3 = r.aug_slot_3; - pd.aug_slot_4 = r.aug_slot_4; - pd.aug_slot_5 = r.aug_slot_5; - pd.aug_slot_6 = r.aug_slot_6; - pd.note = r.note; - pd.quantity = r.quantity; - pd.sent_date = r.sent_date; - pd.char_id = r.char_id; + pd.from_name = r.from_name; + pd.item_id = r.item_id; + pd.augment_1_id = r.aug_slot_1; + pd.augment_2_id = r.aug_slot_2; + pd.augment_3_id = r.aug_slot_3; + pd.augment_4_id = r.aug_slot_4; + pd.augment_5_id = r.aug_slot_5; + pd.augment_6_id = r.aug_slot_6; + pd.note = r.note; + pd.quantity = r.quantity; + pd.sent_date = r.sent_date; + pd.char_id = r.char_id; { cereal::JSONOutputArchiveSingleLine ar(ss); pd.serialize(ar); @@ -2202,3 +2202,20 @@ void Database::ClearBuyerDetails() { BuyerRepository::DeleteBuyer(*this, 0); } + +uint64_t Database::GetNextTableId(const std::string &table_name) +{ + auto results = QueryDatabase(fmt::format("SHOW TABLE STATUS LIKE '{}'", table_name)); + + for (auto row: results) { + for (int row_index = 0; row_index < results.ColumnCount(); row_index++) { + std::string field_name = Strings::ToLower(results.FieldName(row_index)); + if (field_name == "auto_increment") { + std::string value = row[row_index] ? row[row_index] : "null"; + return Strings::ToUnsignedBigInt(value, 1); + } + } + } + + return 1; +} diff --git a/common/database.h b/common/database.h index b33a6acc9..3d263755c 100644 --- a/common/database.h +++ b/common/database.h @@ -274,6 +274,8 @@ public: void Encode(std::string &in); void Decode(std::string &in); + uint64_t GetNextTableId(const std::string& table_name); + private: Mutex Mvarcache; VarCache_Struct varcache; diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 62d0e070a..2bce54033 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -136,11 +136,6 @@ std::string DatabaseDumpService::GetLoginTableList() return Strings::Join(DatabaseSchema::GetLoginTables(), " "); } -std::string DatabaseDumpService::GetQueryServTables() -{ - return Strings::Join(DatabaseSchema::GetQueryServerTables(), " "); -} - std::string DatabaseDumpService::GetSystemTablesList() { auto system_tables = DatabaseSchema::GetServerTables(); @@ -272,11 +267,6 @@ void DatabaseDumpService::DatabaseDump() tables_to_dump += GetLoginTableList() + " "; dump_descriptor += "-login"; } - - if (IsDumpQueryServerTables()) { - tables_to_dump += GetQueryServTables(); - dump_descriptor += "-queryserv"; - } } if (IsDumpStaticInstanceData()) { @@ -401,7 +391,6 @@ void DatabaseDumpService::DatabaseDump() // LogDebug("[{}] dump-to-console", IsDumpOutputToConsole()); // LogDebug("[{}] dump-path", GetSetDumpPath()); // LogDebug("[{}] compression", (IsDumpWithCompression() ? "true" : "false")); -// LogDebug("[{}] query-serv", (IsDumpQueryServerTables() ? "true" : "false")); // LogDebug("[{}] has-compression-binary", (HasCompressionBinary() ? "true" : "false")); // LogDebug("[{}] content", (IsDumpContentTables() ? "true" : "false")); // LogDebug("[{}] no-data", (IsDumpWithNoData() ? "true" : "false")); @@ -511,16 +500,6 @@ const std::string &DatabaseDumpService::GetDumpFileName() const return dump_file_name; } -bool DatabaseDumpService::IsDumpQueryServerTables() const -{ - return dump_query_server_tables; -} - -void DatabaseDumpService::SetDumpQueryServerTables(bool dump_query_server_tables) -{ - DatabaseDumpService::dump_query_server_tables = dump_query_server_tables; -} - bool DatabaseDumpService::IsDumpOutputToConsole() const { return dump_output_to_console; diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 568eac07f..60b252afb 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -45,8 +45,6 @@ public: void SetDumpPath(const std::string &dump_path); const std::string &GetDumpFileName() const; void SetDumpFileName(const std::string &dump_file_name); - bool IsDumpQueryServerTables() const; - void SetDumpQueryServerTables(bool dump_query_server_tables); bool IsDumpOutputToConsole() const; void SetDumpOutputToConsole(bool dump_output_to_console); bool IsDumpDropTableSyntaxOnly() const; @@ -96,7 +94,6 @@ private: bool HasCompressionBinary(); std::string GetDumpFileNameWithPath(); std::string GetSetDumpPath(); - std::string GetQueryServTables(); void RemoveSqlBackup(); void BuildCredentialsFile(); void RemoveCredentialsFile(); diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 40e83a7cb..5d68e717a 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -6505,6 +6505,247 @@ ALTER TABLE `npc_types` ADD COLUMN `multiquest_enabled` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `is_parcel_merchant`; )", .content_schema_update = true + }, + ManifestEntry{ + .version = 9301, + .description = "2024_10_08_add_detail_player_event_logging.sql", + .check = "SHOW COLUMNS FROM `player_event_log_settings` LIKE 'etl_enabled'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `player_event_log_settings` + ADD COLUMN `etl_enabled` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `discord_webhook_id`; +ALTER TABLE `player_event_logs` + ADD COLUMN `etl_table_id` BIGINT(20) NOT NULL DEFAULT '0' AFTER `event_data`; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 14; +CREATE TABLE `player_event_loot_items` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `item_id` INT(10) UNSIGNED NULL DEFAULT NULL, + `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `charges` INT(11) NULL DEFAULT NULL, + `augment_1_id` INT UNSIGNED NULL DEFAULT '0', + `augment_2_id` INT UNSIGNED NULL DEFAULT '0', + `augment_3_id` INT UNSIGNED NULL DEFAULT '0', + `augment_4_id` INT UNSIGNED NULL DEFAULT '0', + `augment_5_id` INT UNSIGNED NULL DEFAULT '0', + `augment_6_id` INT UNSIGNED NULL DEFAULT '0', + `npc_id` INT(10) UNSIGNED NULL DEFAULT NULL, + `corpse_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `item_id_npc_id` (`item_id`, `npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 16; +CREATE TABLE `player_event_merchant_sell` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `merchant_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `merchant_type` INT(10) UNSIGNED NULL DEFAULT '0', + `item_id` INT(10) UNSIGNED NULL DEFAULT '0', + `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `charges` INT(11) NULL DEFAULT '0', + `cost` INT(10) UNSIGNED NULL DEFAULT '0', + `alternate_currency_id` INT(10) UNSIGNED NULL DEFAULT '0', + `player_money_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `player_currency_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `item_id_npc_id` (`item_id`, `npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 15; +CREATE TABLE `player_event_merchant_purchase` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `merchant_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `merchant_type` INT(10) UNSIGNED NULL DEFAULT '0', + `item_id` INT(10) UNSIGNED NULL DEFAULT '0', + `item_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `charges` INT(11) NULL DEFAULT '0', + `cost` INT(10) UNSIGNED NULL DEFAULT '0', + `alternate_currency_id` INT(10) UNSIGNED NULL DEFAULT '0', + `player_money_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `player_currency_balance` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `item_id_npc_id` (`item_id`, `npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 22; +CREATE TABLE `player_event_npc_handin` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `handin_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `handin_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `handin_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `handin_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `return_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `is_quest_handin` TINYINT(3) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id_is_quest_handin` (`npc_id`, `is_quest_handin`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +CREATE TABLE `player_event_npc_handin_entries` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `player_event_npc_handin_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0', + `type` INT(10) UNSIGNED NULL DEFAULT NULL, + `item_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `charges` INT(11) NOT NULL DEFAULT '0', + `evolve_level` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `evolve_amount` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0', + `augment_1_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_2_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_3_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_4_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_5_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `augment_6_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `type_item_id` (`type`, `item_id`) USING BTREE, + INDEX `player_event_npc_handin_id` (`player_event_npc_handin_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 27; +CREATE TABLE `player_event_trade` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `char1_id` INT(10) UNSIGNED NULL DEFAULT '0', + `char2_id` INT(10) UNSIGNED NULL DEFAULT '0', + `char1_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char1_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char1_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char1_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_copper` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_silver` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_gold` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char2_platinum` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `char1_id_char2_id` (`char1_id`, `char2_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +CREATE TABLE `player_event_trade_entries` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `player_event_trade_id` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `char_id` INT(10) UNSIGNED NULL DEFAULT '0', + `slot` SMALLINT(6) NULL DEFAULT '0', + `item_id` INT(10) UNSIGNED NULL DEFAULT '0', + `charges` SMALLINT(6) NULL DEFAULT '0', + `augment_1_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_2_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_3_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_4_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_5_id` INT(10) UNSIGNED NULL DEFAULT '0', + `augment_6_id` INT(10) UNSIGNED NULL DEFAULT '0', + `in_bag` TINYINT(4) NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `player_event_trade_id` (`player_event_trade_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 0 WHERE `id` = 54; +CREATE TABLE `player_event_speech` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `to_char_id` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `from_char_id` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `guild_id` INT(10) UNSIGNED NULL DEFAULT '0', + `type` INT(10) UNSIGNED NULL DEFAULT '0', + `min_status` INT(10) UNSIGNED NULL DEFAULT '0', + `message` LONGTEXT NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `to_char_id_from_char_id` (`to_char_id`, `from_char_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 44; +CREATE TABLE `player_event_killed_npc` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `combat_time_seconds` INT(10) UNSIGNED NULL DEFAULT '0', + `total_damage_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `total_heal_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id` (`npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 45; +CREATE TABLE `player_event_killed_named_npc` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `combat_time_seconds` INT(10) UNSIGNED NULL DEFAULT '0', + `total_damage_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `total_heal_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id` (`npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 46; +CREATE TABLE `player_event_killed_raid_npc` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_id` INT(10) UNSIGNED NULL DEFAULT '0', + `npc_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci', + `combat_time_seconds` INT(10) UNSIGNED NULL DEFAULT '0', + `total_damage_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `total_heal_per_second_taken` BIGINT(20) UNSIGNED NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `npc_id` (`npc_id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; +UPDATE `player_event_log_settings` SET `etl_enabled` = 1 WHERE `id` = 4; +CREATE TABLE `player_event_aa_purchase` ( + `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + `aa_ability_id` INT(11) NULL DEFAULT '0', + `cost` INT(11) NULL DEFAULT '0', + `previous_id` INT(11) NULL DEFAULT '0', + `next_id` INT(11) NULL DEFAULT '0', + `created_at` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `created_at` (`created_at`) USING BTREE +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +; +)" } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/database_schema.h b/common/database_schema.h index 6c0aac9c9..6d1243c8f 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -291,32 +291,6 @@ namespace DatabaseSchema { }; } - /** - * Gets QueryServer tables - * - * @return - */ - static std::vector GetQueryServerTables() - { - return { - "qs_merchant_transaction_record", - "qs_merchant_transaction_record_entries", - "qs_player_aa_rate_hourly", - "qs_player_delete_record", - "qs_player_delete_record_entries", - "qs_player_events", - "qs_player_handin_record", - "qs_player_handin_record_entries", - "qs_player_move_record", - "qs_player_move_record_entries", - "qs_player_npc_kill_record", - "qs_player_npc_kill_record_entries", - "qs_player_speech", - "qs_player_trade_record", - "qs_player_trade_record_entries", - }; - } - /** * Gets state tables * Tables that keep track of server state @@ -359,8 +333,20 @@ namespace DatabaseSchema { "saylink", "server_scheduled_events", "spawn2_disabled", + "player_event_aa_purchase", + "player_event_killed_npc", + "player_event_killed_named_npc", + "player_event_killed_raid_npc", "player_event_log_settings", "player_event_logs", + "player_event_loot_items", + "player_event_merchant_purchase", + "player_event_merchant_sell", + "player_event_npc_handin", + "player_event_npc_handin_entries", + "player_event_speech", + "player_event_trade", + "player_event_trade_entries", "shared_task_activity_state", "shared_task_dynamic_zones", "shared_task_members", diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 40374de8b..fe06c9265 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -147,6 +147,8 @@ void EQEmuConfig::parse_config() QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString(); QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString(); QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); + QSHost = _root["server"]["queryserver"].get("host", "localhost").asString(); + QSPort = Strings::ToUnsignedInt(_root["server"]["queryserver"].get("port", "9500").asString()); /** * Zones diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 0ce295ece..e3924c260 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -81,7 +81,9 @@ class EQEmuConfig std::string QSDatabaseUsername; std::string QSDatabasePassword; std::string QSDatabaseDB; - uint16 QSDatabasePort; + uint16 QSDatabasePort; + std::string QSHost; + int QSPort; // From std::string SpellsFile; diff --git a/common/events/player_event_discord_formatter.cpp b/common/events/player_event_discord_formatter.cpp index 17f3704f5..e3e4e5c27 100644 --- a/common/events/player_event_discord_formatter.cpp +++ b/common/events/player_event_discord_formatter.cpp @@ -1081,51 +1081,51 @@ std::string PlayerEventDiscordFormatter::FormatTradeEvent( if (!e.character_1_give_items.empty()) { for (const auto &i: e.character_1_give_items) { std::string augment_info; - if (i.aug_1_item_id > 0) { + if (i.augment_1_id > 0) { augment_info += fmt::format( "Augment 1: {} ({})", - i.aug_1_item_name, - i.aug_1_item_id + i.augment_1_name, + i.augment_1_id ); } - if (i.aug_2_item_id > 0) { + if (i.augment_2_id > 0) { augment_info += fmt::format( "Augment 2: {} ({})", - i.aug_2_item_name, - i.aug_2_item_id + i.augment_2_name, + i.augment_2_id ); } - if (i.aug_3_item_id > 0) { + if (i.augment_3_id > 0) { augment_info += fmt::format( "Augment 3: {} ({})", - i.aug_3_item_name, - i.aug_3_item_id + i.augment_3_name, + i.augment_3_id ); } - if (i.aug_4_item_id > 0) { + if (i.augment_4_id > 0) { augment_info += fmt::format( "Augment 4: {} ({})\n", - i.aug_4_item_name, - i.aug_4_item_id + i.augment_4_name, + i.augment_4_id ); } - if (i.aug_5_item_id > 0) { + if (i.augment_5_id > 0) { augment_info += fmt::format( "Augment 5: {} ({})\n", - i.aug_5_item_name, - i.aug_5_item_id + i.augment_5_name, + i.augment_5_id ); } - if (i.aug_6_item_id > 0) { + if (i.augment_6_id > 0) { augment_info += fmt::format( "Augment 6: {} ({})", - i.aug_6_item_name, - i.aug_6_item_id + i.augment_6_name, + i.augment_6_id ); } @@ -1146,51 +1146,51 @@ std::string PlayerEventDiscordFormatter::FormatTradeEvent( if (!e.character_2_give_items.empty()) { for (const auto &i: e.character_2_give_items) { std::string augment_info; - if (i.aug_1_item_id > 0) { + if (i.augment_1_id > 0) { augment_info += fmt::format( "Augment 1: {} ({})", - i.aug_1_item_name, - i.aug_1_item_id + i.augment_1_name, + i.augment_1_id ); } - if (i.aug_2_item_id > 0) { + if (i.augment_2_id > 0) { augment_info += fmt::format( "Augment 2: {} ({})", - i.aug_2_item_name, - i.aug_2_item_id + i.augment_2_name, + i.augment_2_id ); } - if (i.aug_3_item_id > 0) { + if (i.augment_3_id > 0) { augment_info += fmt::format( "Augment 3: {} ({})", - i.aug_3_item_name, - i.aug_3_item_id + i.augment_3_name, + i.augment_3_id ); } - if (i.aug_4_item_id > 0) { + if (i.augment_4_id > 0) { augment_info += fmt::format( "Augment 4: {} ({})\n", - i.aug_4_item_name, - i.aug_4_item_id + i.augment_4_name, + i.augment_4_id ); } - if (i.aug_5_item_id > 0) { + if (i.augment_5_id > 0) { augment_info += fmt::format( "Augment 5: {} ({})\n", - i.aug_5_item_name, - i.aug_5_item_id + i.augment_5_name, + i.augment_5_id ); } - if (i.aug_6_item_id > 0) { + if (i.augment_6_id > 0) { augment_info += fmt::format( "Augment 6: {} ({})", - i.aug_6_item_name, - i.aug_6_item_id + i.augment_6_name, + i.augment_6_id ); } diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index 5603fb7b8..191ad21d8 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1,14 +1,21 @@ -#include #include "player_event_logs.h" -#include "player_event_discord_formatter.h" +#include + #include "../platform.h" #include "../rulesys.h" +#include "player_event_discord_formatter.h" +#include "../repositories/player_event_loot_items_repository.h" +#include "../repositories/player_event_merchant_sell_repository.h" +#include "../repositories/player_event_merchant_purchase_repository.h" +#include "../repositories/player_event_npc_handin_repository.h" +#include "../repositories/player_event_npc_handin_entries_repository.h" const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour // general initialization routine void PlayerEventLogs::Init() { + m_process_batch_events_timer.SetTimer(RuleI(Logging, BatchPlayerEventProcessIntervalSeconds) * 1000); m_process_retention_truncation_timer.SetTimer(PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL); @@ -21,6 +28,7 @@ void PlayerEventLogs::Init() m_settings[i].event_enabled = 1; m_settings[i].retention_days = 0; m_settings[i].discord_webhook_id = 0; + m_settings[i].etl_enabled = false; } SetSettingsDefaults(); @@ -65,6 +73,7 @@ void PlayerEventLogs::Init() c.event_name = PlayerEvent::EventName[i]; c.event_enabled = m_settings[i].event_enabled; c.retention_days = m_settings[i].retention_days; + c.etl_enabled = false; settings_to_insert.emplace_back(c); } } @@ -73,6 +82,8 @@ void PlayerEventLogs::Init() PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert); } + LoadEtlIds(); + bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld(); bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ(); @@ -121,23 +132,319 @@ void PlayerEventLogs::ProcessBatchQueue() return; } + static std::map counter{}; + counter.clear(); + for (auto const &e: m_record_batch_queue) { + counter[e.event_type_id]++; + } + BenchTimer benchmark; + EtlQueues etl_queues{}; + for (const auto &[type, count]: counter) { + if (count > 0) { + switch (type) { + case PlayerEvent::TRADE: + etl_queues.trade.reserve(count); + break; + case PlayerEvent::SPEECH: + etl_queues.speech.reserve(count); + break; + case PlayerEvent::LOOT_ITEM: + etl_queues.loot_items.reserve(count); + break; + case PlayerEvent::KILLED_NPC: + etl_queues.killed_npc.reserve(count); + break; + case PlayerEvent::NPC_HANDIN: + etl_queues.npc_handin.reserve(count); + break; + case PlayerEvent::AA_PURCHASE: + etl_queues.aa_purchase.reserve(count); + break; + case PlayerEvent::MERCHANT_SELL: + etl_queues.merchant_sell.reserve(count); + break; + case PlayerEvent::KILLED_RAID_NPC: + etl_queues.killed_raid_npc.reserve(count); + break; + case PlayerEvent::KILLED_NAMED_NPC: + etl_queues.killed_named_npc.reserve(count); + break; + case PlayerEvent::MERCHANT_PURCHASE: + etl_queues.merchant_purchase.reserve(count); + break; + default: + break; + } + } + } + + // Helper to deserialize event data + auto Deserialize = [](const std::string &data, auto &out) { + std::stringstream ss(data); + cereal::JSONInputArchive ar(ss); + out.serialize(ar); + }; + + // Helper to assign ETL table ID + auto AssignEtlId = [&]( + PlayerEventLogsRepository::PlayerEventLogs &r, + PlayerEvent::EventType type + ) { + if (m_etl_settings.contains(type)) { + r.etl_table_id = m_etl_settings.at(type).next_id++; + } + }; + + // Define event processors + std::unordered_map> event_processors = { + { + PlayerEvent::EventType::LOOT_ITEM, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::LootItemEvent in{}; + PlayerEventLootItemsRepository::PlayerEventLootItems out{}; + Deserialize(r.event_data, in); + + out.charges = in.charges; + out.corpse_name = in.corpse_name; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.augment_1_id = in.augment_1_id; + out.augment_2_id = in.augment_2_id; + out.augment_3_id = in.augment_3_id; + out.augment_4_id = in.augment_4_id; + out.augment_5_id = in.augment_5_id; + out.augment_6_id = in.augment_6_id; + out.npc_id = in.npc_id; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::LOOT_ITEM); + etl_queues.loot_items.push_back(out); + } + }, + { + PlayerEvent::EventType::MERCHANT_SELL, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::MerchantSellEvent in{}; + PlayerEventMerchantSellRepository::PlayerEventMerchantSell out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::MERCHANT_SELL); + etl_queues.merchant_sell.push_back(out); + }}, + { + PlayerEvent::EventType::MERCHANT_PURCHASE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::MerchantPurchaseEvent in{}; + PlayerEventMerchantPurchaseRepository::PlayerEventMerchantPurchase out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.merchant_name = in.merchant_name; + out.merchant_type = in.merchant_type; + out.item_id = in.item_id; + out.item_name = in.item_name; + out.charges = in.charges; + out.cost = in.cost; + out.alternate_currency_id = in.alternate_currency_id; + out.player_money_balance = in.player_money_balance; + out.player_currency_balance = in.player_currency_balance; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::MERCHANT_PURCHASE); + etl_queues.merchant_purchase.push_back(out); + }}, + { + PlayerEvent::EventType::NPC_HANDIN, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::HandinEvent in{}; + PlayerEventNpcHandinRepository::PlayerEventNpcHandin out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.handin_copper = in.handin_money.copper; + out.handin_silver = in.handin_money.silver; + out.handin_gold = in.handin_money.gold; + out.handin_platinum = in.handin_money.platinum; + out.return_copper = in.return_money.copper; + out.return_silver = in.return_money.silver; + out.return_gold = in.return_money.gold; + out.return_platinum = in.return_money.platinum; + out.is_quest_handin = in.is_quest_handin; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::NPC_HANDIN); + etl_queues.npc_handin.push_back(out); + + for (const auto &i: in.handin_items) { + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries entry{}; + entry.player_event_npc_handin_id = r.etl_table_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.type = 1; + etl_queues.npc_handin_entries.push_back(entry); + } + for (const auto &i: in.return_items) { + PlayerEventNpcHandinEntriesRepository::PlayerEventNpcHandinEntries entry{}; + entry.player_event_npc_handin_id = r.etl_table_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.type = 2; + etl_queues.npc_handin_entries.push_back(entry); + } + }}, + { + PlayerEvent::EventType::TRADE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::TradeEvent in{}; + PlayerEventTradeRepository::PlayerEventTrade out{}; + Deserialize(r.event_data, in); + + out.char1_id = in.character_1_id; + out.char2_id = in.character_2_id; + out.char1_copper = in.character_1_give_money.copper; + out.char1_silver = in.character_1_give_money.silver; + out.char1_gold = in.character_1_give_money.gold; + out.char1_platinum = in.character_1_give_money.platinum; + out.char2_copper = in.character_2_give_money.copper; + out.char2_silver = in.character_2_give_money.silver; + out.char2_gold = in.character_2_give_money.gold; + out.char2_platinum = in.character_2_give_money.platinum; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::TRADE); + etl_queues.trade.push_back(out); + + for (const auto &i: in.character_1_give_items) { + PlayerEventTradeEntriesRepository::PlayerEventTradeEntries entry{}; + entry.player_event_trade_id = r.etl_table_id; + entry.char_id = in.character_1_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.slot = i.slot; + etl_queues.trade_entries.push_back(entry); + } + for (const auto &i: in.character_2_give_items) { + PlayerEventTradeEntriesRepository::PlayerEventTradeEntries entry{}; + entry.player_event_trade_id = r.etl_table_id; + entry.char_id = in.character_2_id; + entry.item_id = i.item_id; + entry.charges = i.charges; + entry.slot = i.slot; + etl_queues.trade_entries.push_back(entry); + } + }}, + { + PlayerEvent::EventType::SPEECH, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::PlayerSpeech in{}; + PlayerEventSpeechRepository::PlayerEventSpeech out{}; + Deserialize(r.event_data, in); + + out.from_char_id = in.from; + out.to_char_id = in.to; + out.type = in.type; + out.min_status = in.min_status; + out.message = in.message; + out.guild_id = in.guild_id; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::SPEECH); + etl_queues.speech.push_back(out); + }}, + { + PlayerEvent::EventType::KILLED_NPC, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::KilledNPCEvent in{}; + PlayerEventKilledNpcRepository::PlayerEventKilledNpc out{}; + Deserialize(r.event_data, in); + + out.npc_id = in.npc_id; + out.npc_name = in.npc_name; + out.combat_time_seconds = in.combat_time_seconds; + out.total_damage_per_second_taken = in.total_damage_per_second_taken; + out.total_heal_per_second_taken = in.total_heal_per_second_taken; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::KILLED_NPC); + etl_queues.killed_npc.push_back(out); + }}, + { + PlayerEvent::EventType::AA_PURCHASE, [&](PlayerEventLogsRepository::PlayerEventLogs &r) { + PlayerEvent::AAPurchasedEvent in{}; + PlayerEventAaPurchaseRepository::PlayerEventAaPurchase out{}; + Deserialize(r.event_data, in); + + out.aa_ability_id = in.aa_id; + out.cost = in.aa_cost; + out.previous_id = in.aa_previous_id; + out.next_id = in.aa_next_id; + out.created_at = r.created_at; + + AssignEtlId(r, PlayerEvent::EventType::AA_PURCHASE); + etl_queues.aa_purchase.push_back(out); + }}, + }; + + // Process the batch queue + for (auto &r: m_record_batch_queue) { + if (m_settings[r.event_type_id].etl_enabled) { + auto it = event_processors.find(static_cast(r.event_type_id)); + if (it != event_processors.end()) { + it->second(r); // Call the appropriate lambda + r.event_data = "{}"; // Clear event data + } + else { + LogError("Non-Implemented ETL routing [{}]", r.event_type_id); + } + } + } + + // Helper to flush and clear queues + auto flush_queue = [&](auto insert_many, auto &queue) { + if (!queue.empty()) { + insert_many(*m_database, queue); + queue.clear(); + } + }; + // flush many PlayerEventLogsRepository::InsertMany(*m_database, m_record_batch_queue); - LogPlayerEventsDetail( + + // flush etl queues + flush_queue(PlayerEventLootItemsRepository::InsertMany, etl_queues.loot_items); + flush_queue(PlayerEventMerchantSellRepository::InsertMany, etl_queues.merchant_sell); + flush_queue(PlayerEventMerchantPurchaseRepository::InsertMany, etl_queues.merchant_purchase); + flush_queue(PlayerEventNpcHandinRepository::InsertMany, etl_queues.npc_handin); + flush_queue(PlayerEventNpcHandinEntriesRepository::InsertMany, etl_queues.npc_handin_entries); + flush_queue(PlayerEventTradeRepository::InsertMany, etl_queues.trade); + flush_queue(PlayerEventTradeEntriesRepository::InsertMany, etl_queues.trade_entries); + flush_queue(PlayerEventSpeechRepository::InsertMany, etl_queues.speech); + flush_queue(PlayerEventKilledNpcRepository::InsertMany, etl_queues.killed_npc); + flush_queue(PlayerEventKilledNamedNpcRepository::InsertMany, etl_queues.killed_named_npc); + flush_queue(PlayerEventKilledRaidNpcRepository::InsertMany, etl_queues.killed_raid_npc); + flush_queue(PlayerEventAaPurchaseRepository::InsertMany, etl_queues.aa_purchase); + + LogPlayerEvents( "Processing batch player event log queue of [{}] took [{}]", m_record_batch_queue.size(), benchmark.elapsed() ); // empty - m_record_batch_queue = {}; + m_record_batch_queue.clear(); m_batch_queue_lock.unlock(); } // adds a player event to the queue -void PlayerEventLogs::AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &log) +void PlayerEventLogs::AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &log) { m_batch_queue_lock.lock(); m_record_batch_queue.emplace_back(log); @@ -588,7 +895,7 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe break; } default: { - LogInfo( + LogPlayerEventsDetail( "Player event [{}] ({}) Discord formatter not implemented", e.player_event_log.event_type_name, e.player_event_log.event_type_id @@ -602,7 +909,8 @@ std::string PlayerEventLogs::GetDiscordPayloadFromEvent(const PlayerEvent::Playe // general process function, used in world or QS depending on rule Logging:PlayerEventsQSProcess void PlayerEventLogs::Process() { - if (m_process_batch_events_timer.Check() || m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) { + if (m_process_batch_events_timer.Check() || + m_record_batch_queue.size() >= RuleI(Logging, BatchPlayerEventProcessChunkSize)) { ProcessBatchQueue(); } @@ -613,29 +921,115 @@ void PlayerEventLogs::Process() void PlayerEventLogs::ProcessRetentionTruncation() { - LogPlayerEvents("Running truncation"); + LogPlayerEventsDetail("Running truncation"); - for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { + // Map of repository-specific deletion functions + std::unordered_map> repository_deleters = { + { + PlayerEvent::LOOT_ITEM, [&](const std::string &condition) { + return PlayerEventLootItemsRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::MERCHANT_SELL, [&](const std::string &condition) { + return PlayerEventMerchantSellRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::MERCHANT_PURCHASE, [&](const std::string &condition) { + return PlayerEventMerchantPurchaseRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::NPC_HANDIN, [&](const std::string &condition) { + uint32 deleted_count = PlayerEventNpcHandinRepository::DeleteWhere(*m_database, condition); + deleted_count += PlayerEventNpcHandinEntriesRepository::DeleteWhere(*m_database, condition); + return deleted_count; + }}, + { + PlayerEvent::TRADE, [&](const std::string &condition) { + uint32 deleted_count = PlayerEventTradeRepository::DeleteWhere(*m_database, condition); + deleted_count += PlayerEventTradeEntriesRepository::DeleteWhere(*m_database, condition); + return deleted_count; + }}, + { + PlayerEvent::SPEECH, [&](const std::string &condition) { + return PlayerEventSpeechRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::KILLED_NPC, [&](const std::string &condition) { + return PlayerEventKilledNpcRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::KILLED_NAMED_NPC, [&](const std::string &condition) { + return PlayerEventKilledNamedNpcRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::KILLED_RAID_NPC, [&](const std::string &condition) { + return PlayerEventKilledRaidNpcRepository::DeleteWhere(*m_database, condition); + }}, + { + PlayerEvent::AA_PURCHASE, [&](const std::string &condition) { + return PlayerEventAaPurchaseRepository::DeleteWhere(*m_database, condition); + }} + }; + + // Group event types by retention interval + std::unordered_map> retention_groups; + for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { if (m_settings[i].retention_days > 0) { - int deleted_count = PlayerEventLogsRepository::DeleteWhere( - *m_database, - fmt::format( - "event_type_id = {} AND created_at < (NOW() - INTERVAL {} DAY)", - i, - m_settings[i].retention_days - ) - ); + retention_groups[m_settings[i].retention_days].push_back(i); + } + } - if (deleted_count > 0) { - LogInfo( - "Truncated [{}] events of type [{}] ({}) older than [{}] days", - deleted_count, - PlayerEvent::EventName[i], - i, - m_settings[i].retention_days - ); + for (const auto &[retention_days, event_types]: retention_groups) { + std::string condition = fmt::format( + "created_at < (NOW() - INTERVAL {} DAY)", + retention_days + ); + + // Handle ETL deletions for each event type in the group + uint32 total_deleted_count = 0; + for (int event_type_id: event_types) { + if (m_settings[event_type_id].etl_enabled) { + auto it = repository_deleters.find(static_cast(m_settings[event_type_id].id)); + if (it != repository_deleters.end()) { + total_deleted_count += it->second(condition); + } + else { + LogError("Non-Implemented ETL Event Type [{}]", static_cast(m_settings[event_type_id].id)); + } } } + + if (total_deleted_count > 0) { + LogInfo( + "Truncated [{}] ETL events older than [{}] days", + total_deleted_count, + retention_days + ); + } + + // Batch deletion for player_event_logs + std::string event_type_ids = fmt::format( + "({})", + fmt::join(event_types, ", ") + ); + + uint32 deleted_count = PlayerEventLogsRepository::DeleteWhere( + *m_database, + fmt::format( + "event_type_id IN {} AND {}", + event_type_ids, + condition + ) + ); + + if (deleted_count > 0) { + LogInfo( + "Truncated [{}] events of types [{}] older than [{}] days", + deleted_count, + event_type_ids, + retention_days + ); + } } } @@ -708,8 +1102,143 @@ void PlayerEventLogs::SetSettingsDefaults() m_settings[PlayerEvent::PARCEL_DELETE].event_enabled = 1; m_settings[PlayerEvent::BARTER_TRANSACTION].event_enabled = 1; m_settings[PlayerEvent::EVOLVE_ITEM].event_enabled = 1; + m_settings[PlayerEvent::SPEECH].event_enabled = 0; for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) { m_settings[i].retention_days = RETENTION_DAYS_DEFAULT; } } + +void PlayerEventLogs::LoadEtlIds() +{ + auto e = [&](auto p) -> bool { + for (PlayerEventLogSettingsRepository::PlayerEventLogSettings const &c: m_settings) { + if (c.id == p) { + return c.etl_enabled ? true : false; + } + } + + return false; + }; + + m_etl_settings.clear(); + m_etl_settings = { + { + PlayerEvent::LOOT_ITEM, + { + .enabled = e(PlayerEvent::LOOT_ITEM), + .table_name = "player_event_loot_items", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventLootItemsRepository::TableName())) + } + }, + { + PlayerEvent::MERCHANT_SELL, + { + .enabled = e(PlayerEvent::MERCHANT_SELL), + .table_name = "player_event_merchant_sell", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventMerchantSellRepository::TableName())) + } + }, + { + PlayerEvent::MERCHANT_PURCHASE, + { + .enabled = e(PlayerEvent::MERCHANT_PURCHASE), + .table_name = "player_event_merchant_purchase", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventMerchantPurchaseRepository::TableName())) + } + }, + { + PlayerEvent::NPC_HANDIN, + { + .enabled = e(PlayerEvent::NPC_HANDIN), + .table_name = "player_event_npc_handin", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventNpcHandinRepository::TableName())) + + } + }, + { + PlayerEvent::TRADE, + { + .enabled = e(PlayerEvent::TRADE), + .table_name = "player_event_trade", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventTradeRepository::TableName())) + } + }, + { + PlayerEvent::SPEECH, + { + .enabled = e(PlayerEvent::SPEECH), + .table_name = "player_event_speech", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventSpeechRepository::TableName())) + } + }, + { + PlayerEvent::KILLED_NPC, + { + .enabled = e(PlayerEvent::KILLED_NPC), + .table_name = "player_event_killed_npc", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventKilledNpcRepository::TableName())) + } + }, + { + PlayerEvent::KILLED_NAMED_NPC, + { + .enabled = e(PlayerEvent::KILLED_NAMED_NPC), + .table_name = "player_event_killed_named_npc", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventKilledNamedNpcRepository::TableName())) + } + }, + { + PlayerEvent::KILLED_RAID_NPC, + { + .enabled = e(PlayerEvent::KILLED_RAID_NPC), + .table_name = "player_event_killed_raid_npc", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventKilledRaidNpcRepository::TableName())) + } + }, + { + PlayerEvent::AA_PURCHASE, + { + .enabled = e(PlayerEvent::AA_PURCHASE), + .table_name = "player_event_aa_purchase", + .next_id = static_cast(m_database->GetNextTableId(PlayerEventAaPurchaseRepository::TableName())) + } + } + }; + + for (auto &e: m_etl_settings) { + LogPlayerEventsDetail( + "ETL Settings [{}] Enabled [{}] Table [{}] NextId [{}]", + PlayerEvent::EventName[e.first], + e.second.enabled, + e.second.table_name, + e.second.next_id + ); + } +} + +bool PlayerEventLogs::LoadDatabaseConnection() +{ + const auto c = EQEmuConfig::get(); + + LogInfo( + "Connecting to MySQL for PlayerEvents [{}]@[{}]:[{}]", + c->DatabaseUsername.c_str(), + c->DatabaseHost.c_str(), + c->DatabasePort + ); + + if (!player_event_database.Connect( + c->DatabaseHost.c_str(), + c->DatabaseUsername.c_str(), + c->DatabasePassword.c_str(), + c->DatabaseDB.c_str(), + c->DatabasePort + )) { + LogError("Cannot continue without a database connection for player events."); + return false; + } + + SetDatabase(&player_event_database); + return true; +} diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 814f075ba..20220a8be 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -1,19 +1,38 @@ #ifndef EQEMU_PLAYER_EVENT_LOGS_H #define EQEMU_PLAYER_EVENT_LOGS_H -#include "../repositories/player_event_log_settings_repository.h" -#include "player_events.h" -#include "../servertalk.h" -#include "../repositories/player_event_logs_repository.h" -#include "../timer.h" -#include "../json/json_archive_single_line.h" #include #include +#include "../json/json_archive_single_line.h" +#include "../servertalk.h" +#include "../timer.h" +#include "../eqemu_config.h" + +#include "../repositories/player_event_log_settings_repository.h" +#include "../repositories/player_event_logs_repository.h" +#include "../repositories/player_event_loot_items_repository.h" +#include "../repositories/player_event_merchant_purchase_repository.h" +#include "../repositories/player_event_merchant_sell_repository.h" +#include "../repositories/player_event_npc_handin_repository.h" +#include "../repositories/player_event_npc_handin_entries_repository.h" +#include "../repositories/player_event_trade_repository.h" +#include "../repositories/player_event_trade_entries_repository.h" +#include "../repositories/player_event_speech_repository.h" +#include "../repositories/player_event_killed_npc_repository.h" +#include "../repositories/player_event_killed_named_npc_repository.h" +#include "../repositories/player_event_killed_raid_npc_repository.h" +#include "../repositories/player_event_aa_purchase_repository.h" + + class PlayerEventLogs { public: + Database player_event_database{}; + void Init(); + bool LoadDatabaseConnection(); void ReloadSettings(); + void LoadEtlIds(); PlayerEventLogs *SetDatabase(Database *db); bool ValidateDatabaseConnection(); bool IsEventEnabled(PlayerEvent::EventType event); @@ -21,7 +40,7 @@ public: void Process(); // batch queue - void AddToQueue(const PlayerEventLogsRepository::PlayerEventLogs &logs); + void AddToQueue(PlayerEventLogsRepository::PlayerEventLogs &logs); // main event record generic function // can ingest any struct event types @@ -59,7 +78,29 @@ public: std::string GetDiscordWebhookUrlFromEventType(int32_t event_type_id); static std::string GetDiscordPayloadFromEvent(const PlayerEvent::PlayerEventContainer &e); + + struct EtlQueues { + std::vector loot_items; + std::vector merchant_purchase; + std::vector merchant_sell; + std::vector npc_handin; + std::vector npc_handin_entries; + std::vector trade; + std::vector trade_entries; + std::vector speech; + std::vector killed_npc; + std::vector killed_named_npc; + std::vector killed_raid_npc; + std::vector aa_purchase; + }; + private: + struct EtlSettings { + bool enabled; + std::string table_name; + int64 next_id; + }; + Database *m_database; // reference to database PlayerEventLogSettingsRepository::PlayerEventLogSettings m_settings[PlayerEvent::EventType::MAX]{}; @@ -69,6 +110,8 @@ private: static std::unique_ptr BuildPlayerEventPacket(const PlayerEvent::PlayerEventContainer &e); + std::map m_etl_settings{}; + // timers Timer m_process_batch_events_timer; // events processing timer Timer m_process_retention_truncation_timer; // timer for truncating events based on retention settings @@ -78,6 +121,9 @@ private: void ProcessBatchQueue(); void ProcessRetentionTruncation(); void SetSettingsDefaults(); + +public: + std::map &GetEtlSettings() { return m_etl_settings;} }; extern PlayerEventLogs player_event_logs; diff --git a/common/events/player_events.h b/common/events/player_events.h index 6a01a5cf6..177c983d6 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -4,6 +4,7 @@ #include #include #include "../types.h" +#include "../rulesys.h" #include "../repositories/player_event_logs_repository.h" namespace PlayerEvent { @@ -62,6 +63,7 @@ namespace PlayerEvent { PARCEL_RETRIEVE, PARCEL_DELETE, BARTER_TRANSACTION, + SPEECH, EVOLVE_ITEM, MAX // dont remove }; @@ -126,6 +128,7 @@ namespace PlayerEvent { "Parcel Item Retrieved", "Parcel Prune Routine", "Barter Transaction", + "Player Speech", "Evolve Item Update" }; @@ -206,12 +209,12 @@ namespace PlayerEvent { std::string item_name; uint16 to_slot; int16 charges; - uint32 aug1; - uint32 aug2; - uint32 aug3; - uint32 aug4; - uint32 aug5; - uint32 aug6; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; bool attuned; // cereal @@ -223,56 +226,57 @@ namespace PlayerEvent { CEREAL_NVP(item_name), CEREAL_NVP(to_slot), CEREAL_NVP(charges), - CEREAL_NVP(aug1), - CEREAL_NVP(aug2), - CEREAL_NVP(aug3), - CEREAL_NVP(aug4), - CEREAL_NVP(aug5), - CEREAL_NVP(aug6), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(attuned) ); } }; // used in Trade event - struct TradeItem { - int64 item_id; - std::string item_name; - int32 slot; - - // cereal - template - void serialize(Archive &ar) - { - ar( - CEREAL_NVP(item_id), - CEREAL_NVP(item_name), - CEREAL_NVP(slot) - ); - } - }; + // struct TradeItem { + // int64 item_id; + // std::string item_name; + // int32 slot; + // + // // cereal + // template + // void serialize(Archive &ar) + // { + // ar( + // CEREAL_NVP(item_id), + // CEREAL_NVP(item_name), + // CEREAL_NVP(slot) + // ); + // } + // }; // used in Trade event class TradeItemEntry { public: uint16 slot; uint32 item_id; + uint32 augment_1_id; + std::string augment_1_name; + uint32 augment_2_id; + std::string augment_2_name; + uint32 augment_3_id; + std::string augment_3_name; + uint32 augment_4_id; + std::string augment_4_name; + uint32 augment_5_id; + std::string augment_5_name; + uint32 augment_6_id; + std::string augment_6_name; std::string item_name; uint16 charges; - uint32 aug_1_item_id; - std::string aug_1_item_name; - uint32 aug_2_item_id; - std::string aug_2_item_name; - uint32 aug_3_item_id; - std::string aug_3_item_name; - uint32 aug_4_item_id; - std::string aug_4_item_name; - uint32 aug_5_item_id; - std::string aug_5_item_name; - uint32 aug_6_item_id; - std::string aug_6_item_name; bool in_bag; + // cereal template void serialize(Archive &ar) @@ -280,12 +284,20 @@ namespace PlayerEvent { ar( CEREAL_NVP(slot), CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_1_name), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_2_name), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_1_name), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_4_name), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_5_name), + CEREAL_NVP(augment_6_id), + CEREAL_NVP(augment_6_name), + CEREAL_NVP(item_name), CEREAL_NVP(charges), - CEREAL_NVP(aug_1_item_id), - CEREAL_NVP(aug_2_item_id), - CEREAL_NVP(aug_3_item_id), - CEREAL_NVP(aug_4_item_id), - CEREAL_NVP(aug_5_item_id), CEREAL_NVP(in_bag) ); } @@ -399,9 +411,9 @@ namespace PlayerEvent { struct AAPurchasedEvent { uint32 aa_id; - int32 aa_cost; - int32 aa_previous_id; - int32 aa_next_id; + int32 aa_cost; + int32 aa_previous_id; + int32 aa_next_id; // cereal template @@ -418,6 +430,12 @@ namespace PlayerEvent { struct ForageSuccessEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; // cereal @@ -426,6 +444,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name) ); } @@ -433,6 +457,12 @@ namespace PlayerEvent { struct FishSuccessEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; // cereal @@ -441,6 +471,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name) ); } @@ -450,6 +486,13 @@ namespace PlayerEvent { uint32 item_id; std::string item_name; int16 charges; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; + bool attuned; std::string reason; // cereal @@ -459,8 +502,15 @@ namespace PlayerEvent { ar( CEREAL_NVP(item_id), CEREAL_NVP(item_name), - CEREAL_NVP(reason), - CEREAL_NVP(charges) + CEREAL_NVP(charges), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), + CEREAL_NVP(attuned), + CEREAL_NVP(reason) ); } }; @@ -503,6 +553,12 @@ namespace PlayerEvent { uint32 item_id; std::string item_name; int16 charges; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 npc_id; std::string corpse_name; @@ -514,6 +570,12 @@ namespace PlayerEvent { CEREAL_NVP(item_id), CEREAL_NVP(item_name), CEREAL_NVP(charges), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(npc_id), CEREAL_NVP(corpse_name) ); @@ -726,6 +788,12 @@ namespace PlayerEvent { struct DroppedItemEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; int16 slot_id; uint32 charges; @@ -736,6 +804,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name), CEREAL_NVP(slot_id), CEREAL_NVP(charges) @@ -791,6 +865,12 @@ namespace PlayerEvent { struct TraderPurchaseEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; uint32 trader_id; std::string trader_name; @@ -806,6 +886,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name), CEREAL_NVP(trader_id), CEREAL_NVP(trader_name), @@ -819,6 +905,12 @@ namespace PlayerEvent { struct TraderSellEvent { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; std::string item_name; uint32 buyer_id; std::string buyer_name; @@ -834,6 +926,12 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(item_name), CEREAL_NVP(buyer_id), CEREAL_NVP(buyer_name), @@ -964,8 +1062,16 @@ namespace PlayerEvent { }; struct GuildTributeDonateItem { - uint32 item_id; - uint32 guild_favor; + uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; + int16 charges; + bool attuned; + uint32 guild_favor; // cereal template @@ -973,14 +1079,20 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(guild_favor) ); } }; struct GuildTributeDonatePlat { - uint32 plat; - uint32 guild_favor; + uint32 plat; + uint32 guild_favor; // cereal template @@ -995,15 +1107,15 @@ namespace PlayerEvent { struct ParcelRetrieve { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 quantity; std::string from_player_name; uint32 sent_date; - uint32 aug_slot_1; - uint32 aug_slot_2; - uint32 aug_slot_3; - uint32 aug_slot_4; - uint32 aug_slot_5; - uint32 aug_slot_6; // cereal template @@ -1011,31 +1123,31 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(quantity), CEREAL_NVP(from_player_name), - CEREAL_NVP(sent_date), - CEREAL_NVP(aug_slot_1), - CEREAL_NVP(aug_slot_2), - CEREAL_NVP(aug_slot_3), - CEREAL_NVP(aug_slot_4), - CEREAL_NVP(aug_slot_5), - CEREAL_NVP(aug_slot_6) + CEREAL_NVP(sent_date) ); } }; struct ParcelSend { uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; uint32 quantity; std::string from_player_name; std::string to_player_name; uint32 sent_date; - uint32 aug_slot_1; - uint32 aug_slot_2; - uint32 aug_slot_3; - uint32 aug_slot_4; - uint32 aug_slot_5; - uint32 aug_slot_6; // cereal template @@ -1043,33 +1155,33 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(quantity), CEREAL_NVP(from_player_name), CEREAL_NVP(to_player_name), - CEREAL_NVP(sent_date), - CEREAL_NVP(aug_slot_1), - CEREAL_NVP(aug_slot_2), - CEREAL_NVP(aug_slot_3), - CEREAL_NVP(aug_slot_4), - CEREAL_NVP(aug_slot_5), - CEREAL_NVP(aug_slot_6) + CEREAL_NVP(sent_date) ); } }; struct ParcelDelete { - uint32 item_id; - uint32 quantity; uint32 char_id; + uint32 item_id; + uint32 augment_1_id; + uint32 augment_2_id; + uint32 augment_3_id; + uint32 augment_4_id; + uint32 augment_5_id; + uint32 augment_6_id; + uint32 quantity; + uint32 sent_date; std::string from_name; std::string note; - uint32 sent_date; - uint32 aug_slot_1; - uint32 aug_slot_2; - uint32 aug_slot_3; - uint32 aug_slot_4; - uint32 aug_slot_5; - uint32 aug_slot_6; // cereal template @@ -1077,18 +1189,18 @@ namespace PlayerEvent { { ar( CEREAL_NVP(item_id), + CEREAL_NVP(augment_1_id), + CEREAL_NVP(augment_2_id), + CEREAL_NVP(augment_3_id), + CEREAL_NVP(augment_4_id), + CEREAL_NVP(augment_5_id), + CEREAL_NVP(augment_6_id), CEREAL_NVP(quantity), CEREAL_NVP(char_id), CEREAL_NVP(from_name), CEREAL_NVP(note), - CEREAL_NVP(sent_date), - CEREAL_NVP(aug_slot_1), - CEREAL_NVP(aug_slot_2), - CEREAL_NVP(aug_slot_3), - CEREAL_NVP(aug_slot_4), - CEREAL_NVP(aug_slot_5), - CEREAL_NVP(aug_slot_6) - ); + CEREAL_NVP(sent_date) + ); } }; @@ -1140,30 +1252,74 @@ namespace PlayerEvent { ); } }; + + struct PlayerSpeech { + std::string to; + std::string from; + uint32 guild_id; + int16 min_status; + uint32 type; + std::string message; + + template + void serialize(Archive &ar) + { + ar( + CEREAL_NVP(to), + CEREAL_NVP(from), + CEREAL_NVP(guild_id), + CEREAL_NVP(min_status), + CEREAL_NVP(type), + CEREAL_NVP(message) + ); + } + }; } #endif //EQEMU_PLAYER_EVENTS_H #define RecordPlayerEventLog(event_type, event_data) do {\ if (player_event_logs.IsEventEnabled(event_type)) {\ - worldserver.SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ + if (RuleB(Logging, PlayerEventsQSProcess)) {\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + } \ + else { \ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ }\ } while (0) #define RecordPlayerEventLogWithClient(c, event_type, event_data) do {\ if (player_event_logs.IsEventEnabled(event_type)) {\ - worldserver.SendPacket(\ - player_event_logs.RecordEvent(\ - event_type,\ - (c)->GetPlayerEvent(),\ - event_data\ - ).get()\ - );\ + if (RuleB(Logging, PlayerEventsQSProcess)) {\ + QServ->SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ + else {\ + worldserver.SendPacket(\ + player_event_logs.RecordEvent(\ + event_type,\ + (c)->GetPlayerEvent(),\ + event_data\ + ).get()\ + );\ + }\ }\ } while (0) diff --git a/common/net/servertalk_client_connection.h b/common/net/servertalk_client_connection.h index 704b48ded..5a1e3db32 100644 --- a/common/net/servertalk_client_connection.h +++ b/common/net/servertalk_client_connection.h @@ -23,6 +23,9 @@ namespace EQ bool Connected() const { return m_connecting != true; } std::shared_ptr Handle() { return m_connection; } + + const std::unique_ptr &GetTimer() const { return m_timer; } + private: void Connect(); void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length); diff --git a/common/repositories/base/base_player_event_aa_purchase_repository.h b/common/repositories/base/base_player_event_aa_purchase_repository.h new file mode 100644 index 000000000..ca8fb2724 --- /dev/null +++ b/common/repositories/base/base_player_event_aa_purchase_repository.h @@ -0,0 +1,439 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventAaPurchaseRepository { +public: + struct PlayerEventAaPurchase { + uint64_t id; + int32_t aa_ability_id; + int32_t cost; + int32_t previous_id; + int32_t next_id; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "aa_ability_id", + "cost", + "previous_id", + "next_id", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "aa_ability_id", + "cost", + "previous_id", + "next_id", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_aa_purchase"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventAaPurchase NewEntity() + { + PlayerEventAaPurchase e{}; + + e.id = 0; + e.aa_ability_id = 0; + e.cost = 0; + e.previous_id = 0; + e.next_id = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventAaPurchase GetPlayerEventAaPurchase( + const std::vector &player_event_aa_purchases, + int player_event_aa_purchase_id + ) + { + for (auto &player_event_aa_purchase : player_event_aa_purchases) { + if (player_event_aa_purchase.id == player_event_aa_purchase_id) { + return player_event_aa_purchase; + } + } + + return NewEntity(); + } + + static PlayerEventAaPurchase FindOne( + Database& db, + int player_event_aa_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_aa_purchase_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventAaPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.aa_ability_id = row[1] ? static_cast(atoi(row[1])) : 0; + e.cost = row[2] ? static_cast(atoi(row[2])) : 0; + e.previous_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.next_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.created_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_aa_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_aa_purchase_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventAaPurchase &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.aa_ability_id)); + v.push_back(columns[2] + " = " + std::to_string(e.cost)); + v.push_back(columns[3] + " = " + std::to_string(e.previous_id)); + v.push_back(columns[4] + " = " + std::to_string(e.next_id)); + v.push_back(columns[5] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventAaPurchase InsertOne( + Database& db, + PlayerEventAaPurchase e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventAaPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.aa_ability_id = row[1] ? static_cast(atoi(row[1])) : 0; + e.cost = row[2] ? static_cast(atoi(row[2])) : 0; + e.previous_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.next_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.created_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventAaPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.aa_ability_id = row[1] ? static_cast(atoi(row[1])) : 0; + e.cost = row[2] ? static_cast(atoi(row[2])) : 0; + e.previous_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.next_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.created_at = strtoll(row[5] ? row[5] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventAaPurchase &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.aa_ability_id)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.previous_id)); + v.push_back(std::to_string(e.next_id)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_named_npc_repository.h b/common/repositories/base/base_player_event_killed_named_npc_repository.h new file mode 100644 index 000000000..027e5afbf --- /dev/null +++ b/common/repositories/base/base_player_event_killed_named_npc_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventKilledNamedNpcRepository { +public: + struct PlayerEventKilledNamedNpc { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint32_t combat_time_seconds; + uint64_t total_damage_per_second_taken; + uint64_t total_heal_per_second_taken; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_killed_named_npc"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventKilledNamedNpc NewEntity() + { + PlayerEventKilledNamedNpc e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.combat_time_seconds = 0; + e.total_damage_per_second_taken = 0; + e.total_heal_per_second_taken = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventKilledNamedNpc GetPlayerEventKilledNamedNpc( + const std::vector &player_event_killed_named_npcs, + int player_event_killed_named_npc_id + ) + { + for (auto &player_event_killed_named_npc : player_event_killed_named_npcs) { + if (player_event_killed_named_npc.id == player_event_killed_named_npc_id) { + return player_event_killed_named_npc; + } + } + + return NewEntity(); + } + + static PlayerEventKilledNamedNpc FindOne( + Database& db, + int player_event_killed_named_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_killed_named_npc_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventKilledNamedNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_killed_named_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_killed_named_npc_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventKilledNamedNpc &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.combat_time_seconds)); + v.push_back(columns[4] + " = " + std::to_string(e.total_damage_per_second_taken)); + v.push_back(columns[5] + " = " + std::to_string(e.total_heal_per_second_taken)); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventKilledNamedNpc InsertOne( + Database& db, + PlayerEventKilledNamedNpc e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNamedNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNamedNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventKilledNamedNpc &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_npc_repository.h b/common/repositories/base/base_player_event_killed_npc_repository.h new file mode 100644 index 000000000..13fb3fe86 --- /dev/null +++ b/common/repositories/base/base_player_event_killed_npc_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventKilledNpcRepository { +public: + struct PlayerEventKilledNpc { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint32_t combat_time_seconds; + uint64_t total_damage_per_second_taken; + uint64_t total_heal_per_second_taken; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_killed_npc"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventKilledNpc NewEntity() + { + PlayerEventKilledNpc e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.combat_time_seconds = 0; + e.total_damage_per_second_taken = 0; + e.total_heal_per_second_taken = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventKilledNpc GetPlayerEventKilledNpc( + const std::vector &player_event_killed_npcs, + int player_event_killed_npc_id + ) + { + for (auto &player_event_killed_npc : player_event_killed_npcs) { + if (player_event_killed_npc.id == player_event_killed_npc_id) { + return player_event_killed_npc; + } + } + + return NewEntity(); + } + + static PlayerEventKilledNpc FindOne( + Database& db, + int player_event_killed_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_killed_npc_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventKilledNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_killed_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_killed_npc_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventKilledNpc &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.combat_time_seconds)); + v.push_back(columns[4] + " = " + std::to_string(e.total_damage_per_second_taken)); + v.push_back(columns[5] + " = " + std::to_string(e.total_heal_per_second_taken)); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventKilledNpc InsertOne( + Database& db, + PlayerEventKilledNpc e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventKilledNpc &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_raid_npc_repository.h b/common/repositories/base/base_player_event_killed_raid_npc_repository.h new file mode 100644 index 000000000..beba705c6 --- /dev/null +++ b/common/repositories/base/base_player_event_killed_raid_npc_repository.h @@ -0,0 +1,451 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventKilledRaidNpcRepository { +public: + struct PlayerEventKilledRaidNpc { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint32_t combat_time_seconds; + uint64_t total_damage_per_second_taken; + uint64_t total_heal_per_second_taken; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "combat_time_seconds", + "total_damage_per_second_taken", + "total_heal_per_second_taken", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_killed_raid_npc"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventKilledRaidNpc NewEntity() + { + PlayerEventKilledRaidNpc e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.combat_time_seconds = 0; + e.total_damage_per_second_taken = 0; + e.total_heal_per_second_taken = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventKilledRaidNpc GetPlayerEventKilledRaidNpc( + const std::vector &player_event_killed_raid_npcs, + int player_event_killed_raid_npc_id + ) + { + for (auto &player_event_killed_raid_npc : player_event_killed_raid_npcs) { + if (player_event_killed_raid_npc.id == player_event_killed_raid_npc_id) { + return player_event_killed_raid_npc; + } + } + + return NewEntity(); + } + + static PlayerEventKilledRaidNpc FindOne( + Database& db, + int player_event_killed_raid_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_killed_raid_npc_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventKilledRaidNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_killed_raid_npc_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_killed_raid_npc_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventKilledRaidNpc &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.combat_time_seconds)); + v.push_back(columns[4] + " = " + std::to_string(e.total_damage_per_second_taken)); + v.push_back(columns[5] + " = " + std::to_string(e.total_heal_per_second_taken)); + v.push_back(columns[6] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventKilledRaidNpc InsertOne( + Database& db, + PlayerEventKilledRaidNpc e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledRaidNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventKilledRaidNpc e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.combat_time_seconds = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.total_damage_per_second_taken = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.total_heal_per_second_taken = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.created_at = strtoll(row[6] ? row[6] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventKilledRaidNpc &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.combat_time_seconds)); + v.push_back(std::to_string(e.total_damage_per_second_taken)); + v.push_back(std::to_string(e.total_heal_per_second_taken)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index e74156cf1..4a2457576 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -24,6 +24,7 @@ public: int8_t event_enabled; int32_t retention_days; int32_t discord_webhook_id; + uint8_t etl_enabled; }; static std::string PrimaryKey() @@ -39,6 +40,7 @@ public: "event_enabled", "retention_days", "discord_webhook_id", + "etl_enabled", }; } @@ -50,6 +52,7 @@ public: "event_enabled", "retention_days", "discord_webhook_id", + "etl_enabled", }; } @@ -95,6 +98,7 @@ public: e.event_enabled = 0; e.retention_days = 0; e.discord_webhook_id = 0; + e.etl_enabled = 0; return e; } @@ -136,6 +140,7 @@ public: e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.etl_enabled = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; return e; } @@ -174,6 +179,7 @@ public: v.push_back(columns[2] + " = " + std::to_string(e.event_enabled)); v.push_back(columns[3] + " = " + std::to_string(e.retention_days)); v.push_back(columns[4] + " = " + std::to_string(e.discord_webhook_id)); + v.push_back(columns[5] + " = " + std::to_string(e.etl_enabled)); auto results = db.QueryDatabase( fmt::format( @@ -200,6 +206,7 @@ public: v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.etl_enabled)); auto results = db.QueryDatabase( fmt::format( @@ -234,6 +241,7 @@ public: v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.etl_enabled)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -272,6 +280,7 @@ public: e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.etl_enabled = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -301,6 +310,7 @@ public: e.event_enabled = row[2] ? static_cast(atoi(row[2])) : 0; e.retention_days = row[3] ? static_cast(atoi(row[3])) : 0; e.discord_webhook_id = row[4] ? static_cast(atoi(row[4])) : 0; + e.etl_enabled = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -380,6 +390,7 @@ public: v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.etl_enabled)); auto results = db.QueryDatabase( fmt::format( @@ -407,6 +418,7 @@ public: v.push_back(std::to_string(e.event_enabled)); v.push_back(std::to_string(e.retention_days)); v.push_back(std::to_string(e.discord_webhook_id)); + v.push_back(std::to_string(e.etl_enabled)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h index 91f0074b1..3a23feec8 100644 --- a/common/repositories/base/base_player_event_logs_repository.h +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -31,6 +31,7 @@ public: int32_t event_type_id; std::string event_type_name; std::string event_data; + int64_t etl_table_id; time_t created_at; // cereal @@ -50,6 +51,7 @@ public: CEREAL_NVP(event_type_id), CEREAL_NVP(event_type_name), CEREAL_NVP(event_data), + CEREAL_NVP(etl_table_id), CEREAL_NVP(created_at) ); } @@ -75,6 +77,7 @@ public: "event_type_id", "event_type_name", "event_data", + "etl_table_id", "created_at", }; } @@ -94,6 +97,7 @@ public: "event_type_id", "event_type_name", "event_data", + "etl_table_id", "UNIX_TIMESTAMP(created_at)", }; } @@ -147,6 +151,7 @@ public: e.event_type_id = 0; e.event_type_name = ""; e.event_data = ""; + e.etl_table_id = 0; e.created_at = 0; return e; @@ -196,7 +201,8 @@ public: e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; e.event_type_name = row[10] ? row[10] : ""; e.event_data = row[11] ? row[11] : ""; - e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + e.etl_table_id = row[12] ? strtoll(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); return e; } @@ -241,7 +247,8 @@ public: v.push_back(columns[9] + " = " + std::to_string(e.event_type_id)); v.push_back(columns[10] + " = '" + Strings::Escape(e.event_type_name) + "'"); v.push_back(columns[11] + " = '" + Strings::Escape(e.event_data) + "'"); - v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[12] + " = " + std::to_string(e.etl_table_id)); + v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -275,6 +282,7 @@ public: v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -317,6 +325,7 @@ public: v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -363,7 +372,8 @@ public: e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; e.event_type_name = row[10] ? row[10] : ""; e.event_data = row[11] ? row[11] : ""; - e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + e.etl_table_id = row[12] ? strtoll(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -400,7 +410,8 @@ public: e.event_type_id = row[9] ? static_cast(atoi(row[9])) : 0; e.event_type_name = row[10] ? row[10] : ""; e.event_data = row[11] ? row[11] : ""; - e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + e.etl_table_id = row[12] ? strtoll(row[12], nullptr, 10) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -487,6 +498,7 @@ public: v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); auto results = db.QueryDatabase( @@ -522,6 +534,7 @@ public: v.push_back(std::to_string(e.event_type_id)); v.push_back("'" + Strings::Escape(e.event_type_name) + "'"); v.push_back("'" + Strings::Escape(e.event_data) + "'"); + v.push_back(std::to_string(e.etl_table_id)); v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h new file mode 100644 index 000000000..42c1c928a --- /dev/null +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -0,0 +1,523 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventLootItemsRepository { +public: + struct PlayerEventLootItems { + uint64_t id; + uint32_t item_id; + std::string item_name; + int32_t charges; + uint32_t augment_1_id; + uint32_t augment_2_id; + uint32_t augment_3_id; + uint32_t augment_4_id; + uint32_t augment_5_id; + uint32_t augment_6_id; + uint32_t npc_id; + std::string corpse_name; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "item_id", + "item_name", + "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + "npc_id", + "corpse_name", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "item_id", + "item_name", + "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + "npc_id", + "corpse_name", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_loot_items"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventLootItems NewEntity() + { + PlayerEventLootItems e{}; + + e.id = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.augment_1_id = 0; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 0; + e.augment_5_id = 0; + e.augment_6_id = 0; + e.npc_id = 0; + e.corpse_name = ""; + e.created_at = 0; + + return e; + } + + static PlayerEventLootItems GetPlayerEventLootItems( + const std::vector &player_event_loot_itemss, + int player_event_loot_items_id + ) + { + for (auto &player_event_loot_items : player_event_loot_itemss) { + if (player_event_loot_items.id == player_event_loot_items_id) { + return player_event_loot_items; + } + } + + return NewEntity(); + } + + static PlayerEventLootItems FindOne( + Database& db, + int player_event_loot_items_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_loot_items_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventLootItems e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.augment_1_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_2_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_3_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_4_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_5_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_6_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.npc_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.corpse_name = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_loot_items_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_loot_items_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventLootItems &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.item_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.charges)); + v.push_back(columns[4] + " = " + std::to_string(e.augment_1_id)); + v.push_back(columns[5] + " = " + std::to_string(e.augment_2_id)); + v.push_back(columns[6] + " = " + std::to_string(e.augment_3_id)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_4_id)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_5_id)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_6_id)); + v.push_back(columns[10] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[11] + " = '" + Strings::Escape(e.corpse_name) + "'"); + v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventLootItems InsertOne( + Database& db, + PlayerEventLootItems e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventLootItems e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.augment_1_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_2_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_3_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_4_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_5_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_6_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.npc_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.corpse_name = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventLootItems e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.item_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_name = row[2] ? row[2] : ""; + e.charges = row[3] ? static_cast(atoi(row[3])) : 0; + e.augment_1_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.augment_2_id = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.augment_3_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_4_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_5_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_6_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.npc_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.corpse_name = row[11] ? row[11] : ""; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventLootItems &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.corpse_name) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_merchant_purchase_repository.h b/common/repositories/base/base_player_event_merchant_purchase_repository.h new file mode 100644 index 000000000..99ed4e7c5 --- /dev/null +++ b/common/repositories/base/base_player_event_merchant_purchase_repository.h @@ -0,0 +1,511 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventMerchantPurchaseRepository { +public: + struct PlayerEventMerchantPurchase { + uint64_t id; + uint32_t npc_id; + std::string merchant_name; + uint32_t merchant_type; + uint32_t item_id; + std::string item_name; + int32_t charges; + uint32_t cost; + uint32_t alternate_currency_id; + uint64_t player_money_balance; + uint64_t player_currency_balance; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_merchant_purchase"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventMerchantPurchase NewEntity() + { + PlayerEventMerchantPurchase e{}; + + e.id = 0; + e.npc_id = 0; + e.merchant_name = ""; + e.merchant_type = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.cost = 0; + e.alternate_currency_id = 0; + e.player_money_balance = 0; + e.player_currency_balance = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventMerchantPurchase GetPlayerEventMerchantPurchase( + const std::vector &player_event_merchant_purchases, + int player_event_merchant_purchase_id + ) + { + for (auto &player_event_merchant_purchase : player_event_merchant_purchases) { + if (player_event_merchant_purchase.id == player_event_merchant_purchase_id) { + return player_event_merchant_purchase; + } + } + + return NewEntity(); + } + + static PlayerEventMerchantPurchase FindOne( + Database& db, + int player_event_merchant_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_merchant_purchase_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventMerchantPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_merchant_purchase_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_merchant_purchase_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventMerchantPurchase &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.merchant_type)); + v.push_back(columns[4] + " = " + std::to_string(e.item_id)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.charges)); + v.push_back(columns[7] + " = " + std::to_string(e.cost)); + v.push_back(columns[8] + " = " + std::to_string(e.alternate_currency_id)); + v.push_back(columns[9] + " = " + std::to_string(e.player_money_balance)); + v.push_back(columns[10] + " = " + std::to_string(e.player_currency_balance)); + v.push_back(columns[11] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventMerchantPurchase InsertOne( + Database& db, + PlayerEventMerchantPurchase e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantPurchase e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventMerchantPurchase &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_merchant_sell_repository.h b/common/repositories/base/base_player_event_merchant_sell_repository.h new file mode 100644 index 000000000..13c018165 --- /dev/null +++ b/common/repositories/base/base_player_event_merchant_sell_repository.h @@ -0,0 +1,511 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventMerchantSellRepository { +public: + struct PlayerEventMerchantSell { + uint64_t id; + uint32_t npc_id; + std::string merchant_name; + uint32_t merchant_type; + uint32_t item_id; + std::string item_name; + int32_t charges; + uint32_t cost; + uint32_t alternate_currency_id; + uint64_t player_money_balance; + uint64_t player_currency_balance; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "merchant_name", + "merchant_type", + "item_id", + "item_name", + "charges", + "cost", + "alternate_currency_id", + "player_money_balance", + "player_currency_balance", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_merchant_sell"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventMerchantSell NewEntity() + { + PlayerEventMerchantSell e{}; + + e.id = 0; + e.npc_id = 0; + e.merchant_name = ""; + e.merchant_type = 0; + e.item_id = 0; + e.item_name = ""; + e.charges = 0; + e.cost = 0; + e.alternate_currency_id = 0; + e.player_money_balance = 0; + e.player_currency_balance = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventMerchantSell GetPlayerEventMerchantSell( + const std::vector &player_event_merchant_sells, + int player_event_merchant_sell_id + ) + { + for (auto &player_event_merchant_sell : player_event_merchant_sells) { + if (player_event_merchant_sell.id == player_event_merchant_sell_id) { + return player_event_merchant_sell; + } + } + + return NewEntity(); + } + + static PlayerEventMerchantSell FindOne( + Database& db, + int player_event_merchant_sell_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_merchant_sell_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventMerchantSell e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_merchant_sell_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_merchant_sell_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventMerchantSell &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.merchant_type)); + v.push_back(columns[4] + " = " + std::to_string(e.item_id)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.item_name) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.charges)); + v.push_back(columns[7] + " = " + std::to_string(e.cost)); + v.push_back(columns[8] + " = " + std::to_string(e.alternate_currency_id)); + v.push_back(columns[9] + " = " + std::to_string(e.player_money_balance)); + v.push_back(columns[10] + " = " + std::to_string(e.player_currency_balance)); + v.push_back(columns[11] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventMerchantSell InsertOne( + Database& db, + PlayerEventMerchantSell e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantSell e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventMerchantSell e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.merchant_name = row[2] ? row[2] : ""; + e.merchant_type = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.item_name = row[5] ? row[5] : ""; + e.charges = row[6] ? static_cast(atoi(row[6])) : 0; + e.cost = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.alternate_currency_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.player_money_balance = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.player_currency_balance = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventMerchantSell &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.merchant_name) + "'"); + v.push_back(std::to_string(e.merchant_type)); + v.push_back(std::to_string(e.item_id)); + v.push_back("'" + Strings::Escape(e.item_name) + "'"); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.cost)); + v.push_back(std::to_string(e.alternate_currency_id)); + v.push_back(std::to_string(e.player_money_balance)); + v.push_back(std::to_string(e.player_currency_balance)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_npc_handin_entries_repository.h b/common/repositories/base/base_player_event_npc_handin_entries_repository.h new file mode 100644 index 000000000..4d2ee2ead --- /dev/null +++ b/common/repositories/base/base_player_event_npc_handin_entries_repository.h @@ -0,0 +1,523 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventNpcHandinEntriesRepository { +public: + struct PlayerEventNpcHandinEntries { + uint64_t id; + uint64_t player_event_npc_handin_id; + uint32_t type; + uint32_t item_id; + int32_t charges; + uint32_t evolve_level; + uint64_t evolve_amount; + uint32_t augment_1_id; + uint32_t augment_2_id; + uint32_t augment_3_id; + uint32_t augment_4_id; + uint32_t augment_5_id; + uint32_t augment_6_id; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "player_event_npc_handin_id", + "type", + "item_id", + "charges", + "evolve_level", + "evolve_amount", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "player_event_npc_handin_id", + "type", + "item_id", + "charges", + "evolve_level", + "evolve_amount", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_npc_handin_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventNpcHandinEntries NewEntity() + { + PlayerEventNpcHandinEntries e{}; + + e.id = 0; + e.player_event_npc_handin_id = 0; + e.type = 0; + e.item_id = 0; + e.charges = 0; + e.evolve_level = 0; + e.evolve_amount = 0; + e.augment_1_id = 0; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 0; + e.augment_5_id = 0; + e.augment_6_id = 0; + + return e; + } + + static PlayerEventNpcHandinEntries GetPlayerEventNpcHandinEntries( + const std::vector &player_event_npc_handin_entriess, + int player_event_npc_handin_entries_id + ) + { + for (auto &player_event_npc_handin_entries : player_event_npc_handin_entriess) { + if (player_event_npc_handin_entries.id == player_event_npc_handin_entries_id) { + return player_event_npc_handin_entries; + } + } + + return NewEntity(); + } + + static PlayerEventNpcHandinEntries FindOne( + Database& db, + int player_event_npc_handin_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_npc_handin_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventNpcHandinEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_npc_handin_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.type = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.evolve_level = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.evolve_amount = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.augment_1_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_2_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_3_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_4_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_5_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.augment_6_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_npc_handin_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_npc_handin_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventNpcHandinEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.player_event_npc_handin_id)); + v.push_back(columns[2] + " = " + std::to_string(e.type)); + v.push_back(columns[3] + " = " + std::to_string(e.item_id)); + v.push_back(columns[4] + " = " + std::to_string(e.charges)); + v.push_back(columns[5] + " = " + std::to_string(e.evolve_level)); + v.push_back(columns[6] + " = " + std::to_string(e.evolve_amount)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_1_id)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_2_id)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_3_id)); + v.push_back(columns[10] + " = " + std::to_string(e.augment_4_id)); + v.push_back(columns[11] + " = " + std::to_string(e.augment_5_id)); + v.push_back(columns[12] + " = " + std::to_string(e.augment_6_id)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventNpcHandinEntries InsertOne( + Database& db, + PlayerEventNpcHandinEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandinEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_npc_handin_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.type = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.evolve_level = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.evolve_amount = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.augment_1_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_2_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_3_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_4_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_5_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.augment_6_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandinEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_npc_handin_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.type = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.charges = row[4] ? static_cast(atoi(row[4])) : 0; + e.evolve_level = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.evolve_amount = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.augment_1_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_2_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_3_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_4_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_5_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.augment_6_id = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventNpcHandinEntries &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_npc_handin_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.evolve_level)); + v.push_back(std::to_string(e.evolve_amount)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_npc_handin_repository.h b/common/repositories/base/base_player_event_npc_handin_repository.h new file mode 100644 index 000000000..acf460c50 --- /dev/null +++ b/common/repositories/base/base_player_event_npc_handin_repository.h @@ -0,0 +1,523 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventNpcHandinRepository { +public: + struct PlayerEventNpcHandin { + uint64_t id; + uint32_t npc_id; + std::string npc_name; + uint64_t handin_copper; + uint64_t handin_silver; + uint64_t handin_gold; + uint64_t handin_platinum; + uint64_t return_copper; + uint64_t return_silver; + uint64_t return_gold; + uint64_t return_platinum; + uint8_t is_quest_handin; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "npc_id", + "npc_name", + "handin_copper", + "handin_silver", + "handin_gold", + "handin_platinum", + "return_copper", + "return_silver", + "return_gold", + "return_platinum", + "is_quest_handin", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "npc_id", + "npc_name", + "handin_copper", + "handin_silver", + "handin_gold", + "handin_platinum", + "return_copper", + "return_silver", + "return_gold", + "return_platinum", + "is_quest_handin", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_npc_handin"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventNpcHandin NewEntity() + { + PlayerEventNpcHandin e{}; + + e.id = 0; + e.npc_id = 0; + e.npc_name = ""; + e.handin_copper = 0; + e.handin_silver = 0; + e.handin_gold = 0; + e.handin_platinum = 0; + e.return_copper = 0; + e.return_silver = 0; + e.return_gold = 0; + e.return_platinum = 0; + e.is_quest_handin = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventNpcHandin GetPlayerEventNpcHandin( + const std::vector &player_event_npc_handins, + int player_event_npc_handin_id + ) + { + for (auto &player_event_npc_handin : player_event_npc_handins) { + if (player_event_npc_handin.id == player_event_npc_handin_id) { + return player_event_npc_handin; + } + } + + return NewEntity(); + } + + static PlayerEventNpcHandin FindOne( + Database& db, + int player_event_npc_handin_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_npc_handin_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventNpcHandin e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.handin_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.handin_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.handin_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.handin_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.return_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.return_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_npc_handin_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_npc_handin_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventNpcHandin &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.npc_name) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.handin_copper)); + v.push_back(columns[4] + " = " + std::to_string(e.handin_silver)); + v.push_back(columns[5] + " = " + std::to_string(e.handin_gold)); + v.push_back(columns[6] + " = " + std::to_string(e.handin_platinum)); + v.push_back(columns[7] + " = " + std::to_string(e.return_copper)); + v.push_back(columns[8] + " = " + std::to_string(e.return_silver)); + v.push_back(columns[9] + " = " + std::to_string(e.return_gold)); + v.push_back(columns[10] + " = " + std::to_string(e.return_platinum)); + v.push_back(columns[11] + " = " + std::to_string(e.is_quest_handin)); + v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventNpcHandin InsertOne( + Database& db, + PlayerEventNpcHandin e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandin e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.handin_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.handin_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.handin_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.handin_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.return_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.return_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventNpcHandin e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.npc_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.npc_name = row[2] ? row[2] : ""; + e.handin_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.handin_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.handin_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.handin_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.return_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.return_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.return_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.return_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.is_quest_handin = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.created_at = strtoll(row[12] ? row[12] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventNpcHandin &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.npc_id)); + v.push_back("'" + Strings::Escape(e.npc_name) + "'"); + v.push_back(std::to_string(e.handin_copper)); + v.push_back(std::to_string(e.handin_silver)); + v.push_back(std::to_string(e.handin_gold)); + v.push_back(std::to_string(e.handin_platinum)); + v.push_back(std::to_string(e.return_copper)); + v.push_back(std::to_string(e.return_silver)); + v.push_back(std::to_string(e.return_gold)); + v.push_back(std::to_string(e.return_platinum)); + v.push_back(std::to_string(e.is_quest_handin)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_speech_repository.h b/common/repositories/base/base_player_event_speech_repository.h new file mode 100644 index 000000000..80823f3e6 --- /dev/null +++ b/common/repositories/base/base_player_event_speech_repository.h @@ -0,0 +1,463 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventSpeechRepository { +public: + struct PlayerEventSpeech { + uint64_t id; + std::string to_char_id; + std::string from_char_id; + uint32_t guild_id; + uint32_t type; + uint32_t min_status; + std::string message; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "to_char_id", + "from_char_id", + "guild_id", + "type", + "min_status", + "message", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "to_char_id", + "from_char_id", + "guild_id", + "type", + "min_status", + "message", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_speech"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventSpeech NewEntity() + { + PlayerEventSpeech e{}; + + e.id = 0; + e.to_char_id = ""; + e.from_char_id = ""; + e.guild_id = 0; + e.type = 0; + e.min_status = 0; + e.message = ""; + e.created_at = 0; + + return e; + } + + static PlayerEventSpeech GetPlayerEventSpeech( + const std::vector &player_event_speechs, + int player_event_speech_id + ) + { + for (auto &player_event_speech : player_event_speechs) { + if (player_event_speech.id == player_event_speech_id) { + return player_event_speech; + } + } + + return NewEntity(); + } + + static PlayerEventSpeech FindOne( + Database& db, + int player_event_speech_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_speech_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventSpeech e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.to_char_id = row[1] ? row[1] : ""; + e.from_char_id = row[2] ? row[2] : ""; + e.guild_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.type = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.min_status = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.message = row[6] ? row[6] : ""; + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_speech_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_speech_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventSpeech &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = '" + Strings::Escape(e.to_char_id) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.guild_id)); + v.push_back(columns[4] + " = " + std::to_string(e.type)); + v.push_back(columns[5] + " = " + std::to_string(e.min_status)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.message) + "'"); + v.push_back(columns[7] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventSpeech InsertOne( + Database& db, + PlayerEventSpeech e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventSpeech e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.to_char_id = row[1] ? row[1] : ""; + e.from_char_id = row[2] ? row[2] : ""; + e.guild_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.type = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.min_status = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.message = row[6] ? row[6] : ""; + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventSpeech e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.to_char_id = row[1] ? row[1] : ""; + e.from_char_id = row[2] ? row[2] : ""; + e.guild_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.type = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.min_status = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.message = row[6] ? row[6] : ""; + e.created_at = strtoll(row[7] ? row[7] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventSpeech &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back("'" + Strings::Escape(e.to_char_id) + "'"); + v.push_back("'" + Strings::Escape(e.from_char_id) + "'"); + v.push_back(std::to_string(e.guild_id)); + v.push_back(std::to_string(e.type)); + v.push_back(std::to_string(e.min_status)); + v.push_back("'" + Strings::Escape(e.message) + "'"); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_trade_entries_repository.h b/common/repositories/base/base_player_event_trade_entries_repository.h new file mode 100644 index 000000000..ae117e32a --- /dev/null +++ b/common/repositories/base/base_player_event_trade_entries_repository.h @@ -0,0 +1,535 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventTradeEntriesRepository { +public: + struct PlayerEventTradeEntries { + uint64_t id; + uint64_t player_event_trade_id; + uint32_t char_id; + int16_t slot; + uint32_t item_id; + int16_t charges; + uint32_t augment_1_id; + uint32_t augment_2_id; + uint32_t augment_3_id; + uint32_t augment_4_id; + uint32_t augment_5_id; + uint32_t augment_6_id; + int8_t in_bag; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "player_event_trade_id", + "char_id", + "slot", + "item_id", + "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + "in_bag", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "player_event_trade_id", + "char_id", + "slot", + "item_id", + "charges", + "augment_1_id", + "augment_2_id", + "augment_3_id", + "augment_4_id", + "augment_5_id", + "augment_6_id", + "in_bag", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_trade_entries"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventTradeEntries NewEntity() + { + PlayerEventTradeEntries e{}; + + e.id = 0; + e.player_event_trade_id = 0; + e.char_id = 0; + e.slot = 0; + e.item_id = 0; + e.charges = 0; + e.augment_1_id = 0; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 0; + e.augment_5_id = 0; + e.augment_6_id = 0; + e.in_bag = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventTradeEntries GetPlayerEventTradeEntries( + const std::vector &player_event_trade_entriess, + int player_event_trade_entries_id + ) + { + for (auto &player_event_trade_entries : player_event_trade_entriess) { + if (player_event_trade_entries.id == player_event_trade_entries_id) { + return player_event_trade_entries; + } + } + + return NewEntity(); + } + + static PlayerEventTradeEntries FindOne( + Database& db, + int player_event_trade_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_trade_entries_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventTradeEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_trade_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.char_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.slot = row[3] ? static_cast(atoi(row[3])) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.charges = row[5] ? static_cast(atoi(row[5])) : 0; + e.augment_1_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_2_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_3_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_4_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_5_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_6_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.in_bag = row[12] ? static_cast(atoi(row[12])) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_trade_entries_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_trade_entries_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventTradeEntries &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.player_event_trade_id)); + v.push_back(columns[2] + " = " + std::to_string(e.char_id)); + v.push_back(columns[3] + " = " + std::to_string(e.slot)); + v.push_back(columns[4] + " = " + std::to_string(e.item_id)); + v.push_back(columns[5] + " = " + std::to_string(e.charges)); + v.push_back(columns[6] + " = " + std::to_string(e.augment_1_id)); + v.push_back(columns[7] + " = " + std::to_string(e.augment_2_id)); + v.push_back(columns[8] + " = " + std::to_string(e.augment_3_id)); + v.push_back(columns[9] + " = " + std::to_string(e.augment_4_id)); + v.push_back(columns[10] + " = " + std::to_string(e.augment_5_id)); + v.push_back(columns[11] + " = " + std::to_string(e.augment_6_id)); + v.push_back(columns[12] + " = " + std::to_string(e.in_bag)); + v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventTradeEntries InsertOne( + Database& db, + PlayerEventTradeEntries e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTradeEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_trade_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.char_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.slot = row[3] ? static_cast(atoi(row[3])) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.charges = row[5] ? static_cast(atoi(row[5])) : 0; + e.augment_1_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_2_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_3_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_4_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_5_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_6_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.in_bag = row[12] ? static_cast(atoi(row[12])) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTradeEntries e{}; + + e.id = row[0] ? strtoull(row[0], nullptr, 10) : 0; + e.player_event_trade_id = row[1] ? strtoull(row[1], nullptr, 10) : 0; + e.char_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.slot = row[3] ? static_cast(atoi(row[3])) : 0; + e.item_id = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.charges = row[5] ? static_cast(atoi(row[5])) : 0; + e.augment_1_id = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.augment_2_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.augment_3_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.augment_4_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.augment_5_id = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.augment_6_id = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.in_bag = row[12] ? static_cast(atoi(row[12])) : 0; + e.created_at = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventTradeEntries &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.player_event_trade_id)); + v.push_back(std::to_string(e.char_id)); + v.push_back(std::to_string(e.slot)); + v.push_back(std::to_string(e.item_id)); + v.push_back(std::to_string(e.charges)); + v.push_back(std::to_string(e.augment_1_id)); + v.push_back(std::to_string(e.augment_2_id)); + v.push_back(std::to_string(e.augment_3_id)); + v.push_back(std::to_string(e.augment_4_id)); + v.push_back(std::to_string(e.augment_5_id)); + v.push_back(std::to_string(e.augment_6_id)); + v.push_back(std::to_string(e.in_bag)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_trade_repository.h b/common/repositories/base/base_player_event_trade_repository.h new file mode 100644 index 000000000..58409a5cb --- /dev/null +++ b/common/repositories/base/base_player_event_trade_repository.h @@ -0,0 +1,511 @@ +/** + * DO NOT MODIFY THIS FILE + * + * This repository was automatically generated and is NOT to be modified directly. + * Any repository modifications are meant to be made to the repository extending the base. + * Any modifications to base repositories are to be made by the generator only + * + * @generator ./utils/scripts/generators/repository-generator.pl + * @docs https://docs.eqemu.io/developer/repositories + */ + +#ifndef EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H +#define EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BasePlayerEventTradeRepository { +public: + struct PlayerEventTrade { + uint32_t id; + uint32_t char1_id; + uint32_t char2_id; + uint64_t char1_copper; + uint64_t char1_silver; + uint64_t char1_gold; + uint64_t char1_platinum; + uint64_t char2_copper; + uint64_t char2_silver; + uint64_t char2_gold; + uint64_t char2_platinum; + time_t created_at; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "char1_id", + "char2_id", + "char1_copper", + "char1_silver", + "char1_gold", + "char1_platinum", + "char2_copper", + "char2_silver", + "char2_gold", + "char2_platinum", + "created_at", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "char1_id", + "char2_id", + "char1_copper", + "char1_silver", + "char1_gold", + "char1_platinum", + "char2_copper", + "char2_silver", + "char2_gold", + "char2_platinum", + "UNIX_TIMESTAMP(created_at)", + }; + } + + static std::string ColumnsRaw() + { + return std::string(Strings::Implode(", ", Columns())); + } + + static std::string SelectColumnsRaw() + { + return std::string(Strings::Implode(", ", SelectColumns())); + } + + static std::string TableName() + { + return std::string("player_event_trade"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static PlayerEventTrade NewEntity() + { + PlayerEventTrade e{}; + + e.id = 0; + e.char1_id = 0; + e.char2_id = 0; + e.char1_copper = 0; + e.char1_silver = 0; + e.char1_gold = 0; + e.char1_platinum = 0; + e.char2_copper = 0; + e.char2_silver = 0; + e.char2_gold = 0; + e.char2_platinum = 0; + e.created_at = 0; + + return e; + } + + static PlayerEventTrade GetPlayerEventTrade( + const std::vector &player_event_trades, + int player_event_trade_id + ) + { + for (auto &player_event_trade : player_event_trades) { + if (player_event_trade.id == player_event_trade_id) { + return player_event_trade; + } + } + + return NewEntity(); + } + + static PlayerEventTrade FindOne( + Database& db, + int player_event_trade_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {} = {} LIMIT 1", + BaseSelect(), + PrimaryKey(), + player_event_trade_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + PlayerEventTrade e{}; + + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char1_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.char2_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.char1_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.char1_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.char1_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.char1_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.char2_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.char2_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.char2_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.char2_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + return e; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int player_event_trade_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + player_event_trade_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + const PlayerEventTrade &e + ) + { + std::vector v; + + auto columns = Columns(); + + v.push_back(columns[1] + " = " + std::to_string(e.char1_id)); + v.push_back(columns[2] + " = " + std::to_string(e.char2_id)); + v.push_back(columns[3] + " = " + std::to_string(e.char1_copper)); + v.push_back(columns[4] + " = " + std::to_string(e.char1_silver)); + v.push_back(columns[5] + " = " + std::to_string(e.char1_gold)); + v.push_back(columns[6] + " = " + std::to_string(e.char1_platinum)); + v.push_back(columns[7] + " = " + std::to_string(e.char2_copper)); + v.push_back(columns[8] + " = " + std::to_string(e.char2_silver)); + v.push_back(columns[9] + " = " + std::to_string(e.char2_gold)); + v.push_back(columns[10] + " = " + std::to_string(e.char2_platinum)); + v.push_back(columns[11] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", v), + PrimaryKey(), + e.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static PlayerEventTrade InsertOne( + Database& db, + PlayerEventTrade e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", v) + ) + ); + + if (results.Success()) { + e.id = results.LastInsertedID(); + return e; + } + + e = NewEntity(); + + return e; + } + + static int InsertMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All(Database& db) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTrade e{}; + + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char1_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.char2_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.char1_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.char1_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.char1_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.char1_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.char2_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.char2_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.char2_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.char2_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, const std::string &where_filter) + { + std::vector all_entries; + + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE {}", + BaseSelect(), + where_filter + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + PlayerEventTrade e{}; + + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char1_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.char2_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.char1_copper = row[3] ? strtoull(row[3], nullptr, 10) : 0; + e.char1_silver = row[4] ? strtoull(row[4], nullptr, 10) : 0; + e.char1_gold = row[5] ? strtoull(row[5], nullptr, 10) : 0; + e.char1_platinum = row[6] ? strtoull(row[6], nullptr, 10) : 0; + e.char2_copper = row[7] ? strtoull(row[7], nullptr, 10) : 0; + e.char2_silver = row[8] ? strtoull(row[8], nullptr, 10) : 0; + e.char2_gold = row[9] ? strtoull(row[9], nullptr, 10) : 0; + e.char2_platinum = row[10] ? strtoull(row[10], nullptr, 10) : 0; + e.created_at = strtoll(row[11] ? row[11] : "-1", nullptr, 10); + + all_entries.push_back(e); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, const std::string &where_filter) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {}", + TableName(), + where_filter + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int Truncate(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "TRUNCATE TABLE {}", + TableName() + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int64 GetMaxId(Database& db) + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COALESCE(MAX({}), 0) FROM {}", + PrimaryKey(), + TableName() + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static int64 Count(Database& db, const std::string &where_filter = "") + { + auto results = db.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM {} {}", + TableName(), + (where_filter.empty() ? "" : "WHERE " + where_filter) + ) + ); + + return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); + } + + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const PlayerEventTrade &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.char1_id)); + v.push_back(std::to_string(e.char2_id)); + v.push_back(std::to_string(e.char1_copper)); + v.push_back(std::to_string(e.char1_silver)); + v.push_back(std::to_string(e.char1_gold)); + v.push_back(std::to_string(e.char1_platinum)); + v.push_back(std::to_string(e.char2_copper)); + v.push_back(std::to_string(e.char2_silver)); + v.push_back(std::to_string(e.char2_gold)); + v.push_back(std::to_string(e.char2_platinum)); + v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } +}; + +#endif //EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/common/repositories/player_event_aa_purchase_repository.h b/common/repositories/player_event_aa_purchase_repository.h new file mode 100644 index 000000000..189c6c619 --- /dev/null +++ b/common/repositories/player_event_aa_purchase_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_aa_purchase_repository.h" + +class PlayerEventAaPurchaseRepository: public BasePlayerEventAaPurchaseRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_killed_named_npc_repository.h b/common/repositories/player_event_killed_named_npc_repository.h new file mode 100644 index 000000000..bd93fa8ce --- /dev/null +++ b/common/repositories/player_event_killed_named_npc_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_killed_named_npc_repository.h" + +class PlayerEventKilledNamedNpcRepository: public BasePlayerEventKilledNamedNpcRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_npc_repository.h b/common/repositories/player_event_killed_npc_repository.h new file mode 100644 index 000000000..fcbacf7c5 --- /dev/null +++ b/common/repositories/player_event_killed_npc_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_killed_npc_repository.h" + +class PlayerEventKilledNpcRepository: public BasePlayerEventKilledNpcRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_raid_npc_repository.h b/common/repositories/player_event_killed_raid_npc_repository.h new file mode 100644 index 000000000..8b4002c7b --- /dev/null +++ b/common/repositories/player_event_killed_raid_npc_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_killed_raid_npc_repository.h" + +class PlayerEventKilledRaidNpcRepository: public BasePlayerEventKilledRaidNpcRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_log_settings_repository.h b/common/repositories/player_event_log_settings_repository.h index 770db7c3f..10aebc135 100644 --- a/common/repositories/player_event_log_settings_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -2,49 +2,13 @@ #define EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H #include "../database.h" +#include "../events/player_events.h" #include "../strings.h" #include "base/base_player_event_log_settings_repository.h" +#include "base/base_player_event_loot_items_repository.h" class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventLogSettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventLogSettingsRepository::GetWhereNeverExpires() - * PlayerEventLogSettingsRepository::GetWhereXAndY() - * PlayerEventLogSettingsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - }; - #endif //EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/player_event_logs_repository.h b/common/repositories/player_event_logs_repository.h index 97a6d6431..59de5e46c 100644 --- a/common/repositories/player_event_logs_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -7,44 +7,7 @@ class PlayerEventLogsRepository: public BasePlayerEventLogsRepository { public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * PlayerEventLogsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * PlayerEventLogsRepository::GetWhereNeverExpires() - * PlayerEventLogsRepository::GetWhereXAndY() - * PlayerEventLogsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - // Custom extended repository methods here - }; #endif //EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h new file mode 100644 index 000000000..5767d1fb4 --- /dev/null +++ b/common/repositories/player_event_loot_items_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_loot_items_repository.h" + +class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h new file mode 100644 index 000000000..9be7aef6a --- /dev/null +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_merchant_purchase_repository.h" + +class PlayerEventMerchantPurchaseRepository: public BasePlayerEventMerchantPurchaseRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h new file mode 100644 index 000000000..c93131b7a --- /dev/null +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_merchant_sell_repository.h" + +class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_entries_repository.h b/common/repositories/player_event_npc_handin_entries_repository.h new file mode 100644 index 000000000..f3c6d3bbe --- /dev/null +++ b/common/repositories/player_event_npc_handin_entries_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_npc_handin_entries_repository.h" + +class PlayerEventNpcHandinEntriesRepository: public BasePlayerEventNpcHandinEntriesRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_repository.h b/common/repositories/player_event_npc_handin_repository.h new file mode 100644 index 000000000..2b3e23386 --- /dev/null +++ b/common/repositories/player_event_npc_handin_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_npc_handin_repository.h" + +class PlayerEventNpcHandinRepository: public BasePlayerEventNpcHandinRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/player_event_speech_repository.h b/common/repositories/player_event_speech_repository.h new file mode 100644 index 000000000..22f9158fb --- /dev/null +++ b/common/repositories/player_event_speech_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_speech_repository.h" + +class PlayerEventSpeechRepository: public BasePlayerEventSpeechRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/player_event_trade_entries_repository.h b/common/repositories/player_event_trade_entries_repository.h new file mode 100644 index 000000000..775d83370 --- /dev/null +++ b/common/repositories/player_event_trade_entries_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_trade_entries_repository.h" + +class PlayerEventTradeEntriesRepository: public BasePlayerEventTradeEntriesRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_trade_repository.h b/common/repositories/player_event_trade_repository.h new file mode 100644 index 000000000..7813e6fcd --- /dev/null +++ b/common/repositories/player_event_trade_repository.h @@ -0,0 +1,13 @@ +#ifndef EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H +#define EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_player_event_trade_repository.h" + +class PlayerEventTradeRepository: public BasePlayerEventTradeRepository { +public: + // Custom extended repository methods here +}; + +#endif //EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/common/servertalk.h b/common/servertalk.h index 62641ee58..25830afb4 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -304,19 +304,8 @@ #define ServerOP_WWSpell 0x4757 #define ServerOP_WWTaskUpdate 0x4758 -/** - * QueryServer - */ -#define ServerOP_QSPlayerLogTrades 0x5000 -#define ServerOP_QSPlayerLogHandins 0x5001 -#define ServerOP_QSPlayerLogNPCKills 0x5002 -#define ServerOP_QSPlayerLogDeletes 0x5003 -#define ServerOP_QSPlayerLogMoves 0x5004 -#define ServerOP_QSPlayerLogMerchantTransactions 0x5005 -#define ServerOP_QSSendQuery 0x5006 -#define ServerOP_QSPlayerDropItem 0x5007 - // player events +#define ServerOP_QSSendQuery 0x5000 #define ServerOP_PlayerEvent 0x5100 enum { @@ -400,7 +389,6 @@ enum { QSG_LFGuild = 0 }; enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_RequestPlayerInfo, QSG_LFGuild_UpdateGuildInfo, QSG_LFGuild_GuildMatches, QSG_LFGuild_RequestGuildInfo }; -#define ServerOP_Speech 0x5500 enum { UserToWorldStatusWorldUnavail = 0, @@ -1358,171 +1346,11 @@ struct ServerMailMessageHeader_Struct { char message[0]; }; -struct Server_Speech_Struct { - char to[64]; - char from[64]; - uint32 guilddbid; - int16 minstatus; - uint32 type; - char message[0]; -}; - -struct PlayerLogTradeItemsEntry_Struct { - uint32 from_character_id; - uint16 from_slot; - uint32 to_character_id; - uint16 to_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct PlayerLogTrade_Struct { - uint32 character_1_id; - MoneyUpdate_Struct character_1_money; - uint16 character_1_item_count; - uint32 character_2_id; - MoneyUpdate_Struct character_2_money; - uint16 character_2_item_count; - uint16 _detail_count; - PlayerLogTradeItemsEntry_Struct item_entries[0]; -}; - -struct QSDropItems_Struct { - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerDropItem_Struct { - uint32 char_id; - bool pickup; // 0 drop, 1 pickup - uint32 zone_id; - int x; - int y; - int z; - uint16 _detail_count; - QSDropItems_Struct items[0]; -}; - -struct QSHandinItems_Struct { - char action_type[7]; // handin, return or reward - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogHandin_Struct { - uint32 quest_id; - uint32 char_id; - MoneyUpdate_Struct char_money; - uint16 char_count; - uint32 npc_id; - MoneyUpdate_Struct npc_money; - uint16 npc_count; - uint16 _detail_count; - QSHandinItems_Struct items[0]; -}; - -struct QSPlayerLogNPCKillSub_Struct{ - uint32 NPCID; - uint32 ZoneID; - uint32 Type; -}; - -struct QSPlayerLogNPCKillsPlayers_Struct{ - uint32 char_id; -}; - -struct QSPlayerLogNPCKill_Struct{ - QSPlayerLogNPCKillSub_Struct s1; - QSPlayerLogNPCKillsPlayers_Struct Chars[0]; -}; - -struct QSDeleteItems_Struct { - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogDelete_Struct { - uint32 char_id; - uint16 stack_size; // '0' indicates full stack or non-stackable item move - uint16 char_count; - QSDeleteItems_Struct items[0]; -}; - -struct QSMoveItems_Struct { - uint16 from_slot; - uint16 to_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogMove_Struct { - uint32 char_id; - uint16 from_slot; - uint16 to_slot; - uint16 stack_size; // '0' indicates full stack or non-stackable item move - uint16 char_count; - bool postaction; - QSMoveItems_Struct items[0]; -}; - -struct QSTransactionItems_Struct { - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSMerchantLogTransaction_Struct { - uint32 zone_id; - uint32 merchant_id; - MoneyUpdate_Struct merchant_money; - uint16 merchant_count; - uint32 char_id; - MoneyUpdate_Struct char_money; - uint16 char_count; - QSTransactionItems_Struct items[0]; -}; - struct DiscordWebhookMessage_Struct { uint32 webhook_id; char message[2000]; }; -struct QSGeneralQuery_Struct { - char QueryString[0]; -}; - struct CZClientMessageString_Struct { uint32 string_id; uint16 chat_type; diff --git a/common/version.h b/common/version.h index 6798d42b3..fc1c5c816 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9300 +#define CURRENT_BINARY_DATABASE_VERSION 9301 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #endif diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index bd6e37ecd..82613065a 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -6,6 +6,8 @@ SET(qserv_sources queryserv.cpp queryservconfig.cpp worldserver.cpp + zonelist.cpp + zoneserver.cpp ) SET(qserv_headers @@ -13,6 +15,8 @@ SET(qserv_headers lfguild.h queryservconfig.h worldserver.h + zonelist.h + zoneserver.h ) ADD_EXECUTABLE(queryserv ${qserv_sources} ${qserv_headers}) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 5bd21ac5e..db6be3ce2 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -1,386 +1,9 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - - #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include -#include -#include -#include -#include -#include -#include -#include #include -#include - -// Disgrace: for windows compile -#ifdef _WINDOWS -#include -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else - -#include "../common/unix.h" -#include - -#endif - #include "database.h" -#include "../common/eq_packet_structs.h" #include "../common/strings.h" -#include "../common/servertalk.h" - -void QSDatabase::AddSpeech( - const char *from, - const char *to, - const char *message, - uint16 minstatus, - uint32 guilddbid, - uint8 type -) -{ - - auto escapedFrom = new char[strlen(from) * 2 + 1]; - auto escapedTo = new char[strlen(to) * 2 + 1]; - auto escapedMessage = new char[strlen(message) * 2 + 1]; - DoEscapeString(escapedFrom, from, strlen(from)); - DoEscapeString(escapedTo, to, strlen(to)); - DoEscapeString(escapedMessage, message, strlen(message)); - - std::string query = StringFormat( - "INSERT INTO `qs_player_speech` " - "SET `from` = '%s', `to` = '%s', `message`='%s', " - "`minstatus`='%i', `guilddbid`='%i', `type`='%i'", - escapedFrom, escapedTo, escapedMessage, minstatus, guilddbid, type - ); - safe_delete_array(escapedFrom); - safe_delete_array(escapedTo); - safe_delete_array(escapedMessage); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Speech Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - -} - -void QSDatabase::LogPlayerDropItem(QSPlayerDropItem_Struct *QS) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_drop_record` SET `time` = NOW(), " - "`char_id` = '%i', `pickup` = '%i', " - "`zone_id` = '%i', `x` = '%i', `y` = '%i', `z` = '%i' ", - QS->char_id, QS->pickup, QS->zone_id, QS->x, QS->y, QS->z - ); - - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Drop Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (QS->_detail_count == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < QS->_detail_count; i++) { - query = StringFormat( - "INSERT INTO `qs_player_drop_record_entries` SET `event_id` = '%i', " - "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " - "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Drop Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - } -} - -void QSDatabase::LogPlayerTrade(PlayerLogTrade_Struct *QS, uint32 detailCount) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_trade_record` SET `time` = NOW(), " - "`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', " - "`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', " - "`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', " - "`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'", - QS->character_1_id, QS->character_1_money.platinum, QS->character_1_money.gold, - QS->character_1_money.silver, QS->character_1_money.copper, QS->character_1_item_count, - QS->character_2_id, QS->character_2_money.platinum, QS->character_2_money.gold, - QS->character_2_money.silver, QS->character_2_money.copper, QS->character_2_item_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Trade Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (detailCount == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < detailCount; i++) { - query = StringFormat( - "INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', " - "`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', " - "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " - "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->item_entries[i].from_character_id, QS->item_entries[i].from_slot, - QS->item_entries[i].to_character_id, QS->item_entries[i].to_slot, QS->item_entries[i].item_id, - QS->item_entries[i].charges, QS->item_entries[i].aug_1, QS->item_entries[i].aug_2, - QS->item_entries[i].aug_3, QS->item_entries[i].aug_4, QS->item_entries[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Trade Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} - -void QSDatabase::LogPlayerHandin(QSPlayerLogHandin_Struct *QS, uint32 detailCount) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_handin_record` SET `time` = NOW(), " - "`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', " - "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " - "`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', " - "`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', " - "`npc_items`='%i'", - QS->quest_id, QS->char_id, QS->char_money.platinum, - QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, - QS->char_count, QS->npc_id, QS->npc_money.platinum, - QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, - QS->npc_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Handin Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (detailCount == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < detailCount; i++) { - query = StringFormat( - "INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', " - "`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', " - "`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', " - "`aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].action_type, QS->items[i].char_slot, - QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1, - QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5 - ); - auto results = QueryDatabase(query); - - if (!results.Success()) { - LogInfo("Failed Handin Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - } - -} - -void QSDatabase::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct *QS, uint32 members) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_npc_kill_record` " - "SET `npc_id` = '%i', `type` = '%i', " - "`zone_id` = '%i', `time` = NOW()", - QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed NPC Kill Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (members == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < members; i++) { - query = StringFormat( - "INSERT INTO `qs_player_npc_kill_record_entries` " - "SET `event_id` = '%i', `char_id` = '%i'", - lastIndex, QS->Chars[i].char_id - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed NPC Kill Log Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} - -void QSDatabase::LogPlayerDelete(QSPlayerLogDelete_Struct *QS, uint32 items) -{ - - std::string query = StringFormat( - "INSERT INTO `qs_player_delete_record` SET `time` = NOW(), " - "`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'", - QS->char_id, QS->stack_size, QS->char_count, QS->char_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Delete Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (items == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < items; i++) { - query = StringFormat( - "INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', " - "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " - "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Delete Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} - -void QSDatabase::LogPlayerMove(QSPlayerLogMove_Struct *QS, uint32 items) -{ - /* These are item moves */ - - std::string query = StringFormat( - "INSERT INTO `qs_player_move_record` SET `time` = NOW(), " - "`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', " - "`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'", - QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, - QS->char_count, QS->postaction - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Move Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (items == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < items; i++) { - query = StringFormat( - "INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', " - "`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', " - "`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Move Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - } -} - -void QSDatabase::LogMerchantTransaction(QSMerchantLogTransaction_Struct *QS, uint32 items) -{ - /* Merchant transactions are from the perspective of the merchant, not the player */ - std::string query = StringFormat( - "INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), " - "`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', " - "`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', " - "`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', " - "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " - "`char_items` = '%i'", - QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, - QS->merchant_money.gold, QS->merchant_money.silver, - QS->merchant_money.copper, QS->merchant_count, QS->char_id, - QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, - QS->char_money.copper, QS->char_count - ); - auto results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Transaction Log Record Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - if (items == 0) { - return; - } - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < items; i++) { - query = StringFormat( - "INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', " - "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " - "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5 - ); - results = QueryDatabase(query); - if (!results.Success()) { - LogInfo("Failed Transaction Log Record Entry Insert: [{}]", results.ErrorMessage().c_str()); - LogInfo("[{}]", query.c_str()); - } - - } - -} // this function does not delete the ServerPacket, so it must be handled at call site void QSDatabase::GeneralQueryReceive(ServerPacket *pack) @@ -388,7 +11,7 @@ void QSDatabase::GeneralQueryReceive(ServerPacket *pack) /* These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again */ - auto queryBuffer = new char[pack->ReadUInt32() + 1]; + auto queryBuffer = new char[pack->ReadUInt32() + 1]; pack->ReadString(queryBuffer); std::string query(queryBuffer); diff --git a/queryserv/database.h b/queryserv/database.h index 5072f5b55..69b0b8e36 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -1,22 +1,3 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - #ifndef CHATSERVER_DATABASE_H #define CHATSERVER_DATABASE_H @@ -33,17 +14,8 @@ #include #include - class QSDatabase : public Database { public: - void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type); - void LogPlayerTrade(PlayerLogTrade_Struct* QS, uint32 DetailCount); - void LogPlayerDropItem(QSPlayerDropItem_Struct* QS); - void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount); - void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members); - void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items); - void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items); - void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items); void GeneralQueryReceive(ServerPacket *pack); }; diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index 5e80a8511..688102ed1 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -1,14 +1,11 @@ -#include #include "lfguild.h" #include "database.h" #include "worldserver.h" -#include "../common/eqemu_logsys.h" #include "../common/strings.h" -#include "../common/packet_dump.h" #include "../common/rulesys.h" extern WorldServer *worldserver; -extern QSDatabase database; +extern QSDatabase qs_database; PlayerLookingForGuild::PlayerLookingForGuild(char *name, char *comments, uint32 level, uint32 classes, uint32 aa_count, uint32 time_zone, uint32 time_posted) { @@ -38,7 +35,7 @@ bool LFGuildManager::LoadDatabase() std::string query = "SELECT `type`,`name`,`comment`, " "`fromlevel`, `tolevel`, `classes`, " "`aacount`, `timezone`, `timeposted` FROM `lfguild`"; - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); if (!results.Success()) { return false; } @@ -239,7 +236,7 @@ void LFGuildManager::TogglePlayer(uint32 FromZoneID, uint32 FromInstanceID, char } std::string query = StringFormat("DELETE FROM `lfguild` WHERE `type` = 0 AND `name` = '%s'", From); - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); uint32 Now = time(nullptr); @@ -252,7 +249,7 @@ void LFGuildManager::TogglePlayer(uint32 FromZoneID, uint32 FromInstanceID, char "`classes`, `aacount`, `timezone`, `timeposted`) " "VALUES (0, '%s', '%s', %u, 0, %u, %u, %u, %u)", From, Comments, Level, Class, AAPoints, TimeZone, Now); - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); } auto pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + strlen(Comments) + 30); @@ -281,7 +278,7 @@ void LFGuildManager::ToggleGuild(uint32 FromZoneID, uint32 FromInstanceID, char } std::string query = StringFormat("DELETE FROM `lfguild` WHERE `type` = 1 AND `name` = '%s'", GuildName); - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); uint32 Now = time(nullptr); @@ -296,7 +293,7 @@ void LFGuildManager::ToggleGuild(uint32 FromZoneID, uint32 FromInstanceID, char "VALUES (1, '%s', '%s', %u, %u, %u, %u, %u, %u)", GuildName, Comments, FromLevel, ToLevel, Classes, AACount, TimeZone, Now); - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); } @@ -324,7 +321,7 @@ void LFGuildManager::ExpireEntries() continue; std::string query = StringFormat("DELETE from `lfguild` WHERE `type` = 0 AND `name` = '%s'", (*it).Name.c_str()); - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); if(!results.Success()) it = Players.erase(it); @@ -336,7 +333,7 @@ void LFGuildManager::ExpireEntries() continue; std::string query = StringFormat("DELETE from `lfguild` WHERE `type` = 1 AND `name` = '%s'", (*it2).Name.c_str()); - auto results = database.QueryDatabase(query); + auto results = qs_database.QueryDatabase(query); if(!results.Success()) it2 = Guilds.erase(it2); diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index a504b8e77..cbcf60d35 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -1,27 +1,7 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/opcodemgr.h" #include "../common/rulesys.h" -#include "../common/servertalk.h" #include "../common/platform.h" #include "../common/crash.h" #include "../common/strings.h" @@ -31,16 +11,21 @@ #include "queryservconfig.h" #include "lfguild.h" #include "worldserver.h" -#include "../common/path_manager.h" #include "../common/zone_store.h" #include "../common/events/player_event_logs.h" #include #include #include +#include "../common/net/servertalk_server.h" +#include "../common/net/console_server.h" +#include "../queryserv/zonelist.h" +#include "../queryserv/zoneserver.h" +#include "../common/discord/discord_manager.h" volatile bool RunLoops = true; -QSDatabase database; +QSDatabase qs_database; +Database database; LFGuildManager lfguildmanager; std::string WorldShortName; const queryservconfig *Config; @@ -49,6 +34,9 @@ EQEmuLogSys LogSys; PathManager path; ZoneStore zone_store; PlayerEventLogs player_event_logs; +ZSList zs_list; +uint32 numzones = 0; +DiscordManager discord_manager; void CatchSignal(int sig_num) { @@ -76,12 +64,22 @@ int main() LogInfo("Connecting to MySQL"); /* MySQL Connection */ - if (!database.Connect( + if (!qs_database.Connect( Config->QSDatabaseHost.c_str(), Config->QSDatabaseUsername.c_str(), Config->QSDatabasePassword.c_str(), Config->QSDatabaseDB.c_str(), Config->QSDatabasePort + )) { + LogInfo("Cannot continue without a qs database connection"); + return 1; + } + if (!database.Connect( + Config->DatabaseHost.c_str(), + Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), + Config->DatabaseDB.c_str(), + Config->DatabasePort )) { LogInfo("Cannot continue without a database connection"); return 1; @@ -101,6 +99,61 @@ int main() return 1; } + //rules: + { + std::string tmp; + if (database.GetVariable("RuleSet", tmp)) { + LogInfo("Loading rule set [{}]", tmp.c_str()); + if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { + LogError("Failed to load ruleset [{}], falling back to defaults", tmp.c_str()); + } + } + else { + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { + LogInfo("No rule set configured, using default rules"); + } + } + + EQ::InitializeDynamicLookups(); + } + + std::unique_ptr console; + EQ::Net::ServertalkServerOptions server_opts; + auto server_connection = std::make_unique(); + server_opts.port = Config->QSPort; + server_opts.ipv6 = false; + server_opts.credentials = Config->SharedKey; + server_connection->Listen(server_opts); + LogInfo("Server (TCP) listener started on port [{}]", Config->QSPort); + + server_connection->OnConnectionIdentified( + "Zone", [&console](std::shared_ptr connection) { + numzones++; + zs_list.Add(new ZoneServer(connection, console.get())); + + LogInfo( + "New Zone Server connection from [{}] at [{}:{}] zone_count [{}]", + connection->Handle()->RemoteIP(), + connection->Handle()->RemotePort(), + connection->GetUUID(), + numzones + ); + } + ); + + server_connection->OnConnectionRemoved( + "Zone", [](std::shared_ptr connection) { + numzones--; + zs_list.Remove(connection->GetUUID()); + + LogInfo( + "Removed Zone Server connection from [{}] total zone_count [{}]", + connection->GetUUID(), + numzones + ); + } + ); + /* Initial Connection to Worldserver */ worldserver = new WorldServer; worldserver->Connect(); @@ -109,9 +162,9 @@ int main() lfguildmanager.LoadDatabase(); Timer player_event_process_timer(1000); - player_event_logs.SetDatabase(&database)->Init(); + player_event_logs.SetDatabase(&qs_database)->Init(); - auto loop_fn = [&](EQ::Timer* t) { + auto loop_fn = [&](EQ::Timer *t) { Timer::SetCurrentTime(); if (!RunLoops) { @@ -124,7 +177,7 @@ int main() } if (player_event_process_timer.Check()) { - player_event_logs.Process(); + std::jthread player_event_thread(&PlayerEventLogs::Process, &player_event_logs); } }; @@ -133,6 +186,7 @@ int main() EQ::EventLoop::Get().Run(); + safe_delete(worldserver); LogSys.CloseFileLogs(); } diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index f46baf983..0ff8698d5 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -1,22 +1,3 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "../common/md5.h" @@ -41,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA extern WorldServer worldserver; extern const queryservconfig *Config; -extern QSDatabase database; +extern QSDatabase qs_database; extern LFGuildManager lfguildmanager; WorldServer::WorldServer() @@ -91,65 +72,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) case 0: { break; } - case ServerOP_PlayerEvent: { - auto n = PlayerEvent::PlayerEventContainer{}; - auto s = (ServerSendPlayerEvent_Struct *) p.Data(); - EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size); - cereal::BinaryInputArchive archive(ss); - archive(n); - - player_event_logs.AddToQueue(n.player_event_log); - - break; - } - case ServerOP_KeepAlive: { - break; - } - case ServerOP_Speech: { - Server_Speech_Struct *SSS = (Server_Speech_Struct *) p.Data(); - std::string tmp1 = SSS->from; - std::string tmp2 = SSS->to; - database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type); - break; - } - case ServerOP_QSPlayerLogTrades: { - PlayerLogTrade_Struct *QS = (PlayerLogTrade_Struct *) p.Data(); - database.LogPlayerTrade(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerDropItem: { - QSPlayerDropItem_Struct *QS = (QSPlayerDropItem_Struct *) p.Data(); - database.LogPlayerDropItem(QS); - break; - } - case ServerOP_QSPlayerLogHandins: { - QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct *) p.Data(); - database.LogPlayerHandin(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerLogNPCKills: { - QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct *) p.Data(); - uint32 Members = (uint32) (p.Length() - sizeof(QSPlayerLogNPCKill_Struct)); - if (Members > 0) { Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct); } - database.LogPlayerNPCKill(QS, Members); - break; - } - case ServerOP_QSPlayerLogDeletes: { - QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct *) p.Data(); - uint32 Items = QS->char_count; - database.LogPlayerDelete(QS, Items); - break; - } - case ServerOP_QSPlayerLogMoves: { - QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct *) p.Data(); - uint32 Items = QS->char_count; - database.LogPlayerMove(QS, Items); - break; - } - case ServerOP_QSPlayerLogMerchantTransactions: { - QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct *) p.Data(); - uint32 Items = QS->char_count + QS->merchant_count; - database.LogMerchantTransaction(QS, Items); + case ServerOP_ReloadLogs: { + LogSys.LoadLogDatabaseSettings(); + player_event_logs.ReloadSettings(); break; } case ServerOP_QueryServGeneric: { @@ -199,9 +124,12 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) pack.opcode = opcode; pack.size = (uint32) p.Length(); - database.GeneralQueryReceive(&pack); + qs_database.GeneralQueryReceive(&pack); pack.pBuffer = nullptr; break; } + default: + LogInfo("Unhandled opcode: {}", opcode); + break; } } diff --git a/queryserv/zonelist.cpp b/queryserv/zonelist.cpp new file mode 100644 index 000000000..d06cfefe8 --- /dev/null +++ b/queryserv/zonelist.cpp @@ -0,0 +1,20 @@ +#include "zonelist.h" +#include "zoneserver.h" +#include "../common/strings.h" + +void ZSList::Add(ZoneServer* zoneserver) { + zone_server_list.emplace_back(std::unique_ptr(zoneserver)); + zoneserver->SetIsZoneConnected(true); +} + +void ZSList::Remove(const std::string &uuid) +{ + auto iter = zone_server_list.begin(); + while (iter != zone_server_list.end()) { + if ((*iter)->GetUUID().compare(uuid) == 0) { + zone_server_list.erase(iter); + return; + } + iter++; + } +} diff --git a/queryserv/zonelist.h b/queryserv/zonelist.h new file mode 100644 index 000000000..c63d1c211 --- /dev/null +++ b/queryserv/zonelist.h @@ -0,0 +1,23 @@ +#ifndef ZONELIST_H_ +#define ZONELIST_H_ + +#include "../common/types.h" +#include +#include +#include +#include + +class WorldTCPConnection; +class ZoneServer; + +class ZSList { +public: + std::list> &GetZsList() { return zone_server_list; } + void Add(ZoneServer *zoneserver); + void Remove(const std::string &uuid); + +private: + std::list> zone_server_list; +}; + +#endif /*ZONELIST_H_*/ diff --git a/queryserv/zoneserver.cpp b/queryserv/zoneserver.cpp new file mode 100644 index 000000000..2c3fd92d4 --- /dev/null +++ b/queryserv/zoneserver.cpp @@ -0,0 +1,48 @@ +#include "zoneserver.h" +#include "../common/global_define.h" +#include "../common/eqemu_logsys.h" +#include "../common/repositories/player_event_logs_repository.h" +#include "../common/events/player_event_logs.h" +#include "../common/discord/discord_manager.h" + +extern DiscordManager discord_manager; + +ZoneServer::ZoneServer( + std::shared_ptr in_connection, + EQ::Net::ConsoleServer *in_console +) + : m_connection(in_connection) +{ + + m_connection->OnMessage(std::bind(&ZoneServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); + m_console = in_console; +} + +ZoneServer::~ZoneServer() +{ +} + +void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) +{ + ServerPacket tpack(opcode, p); + auto pack = &tpack; + + switch (opcode) { + case ServerOP_PlayerEvent: { + auto n = PlayerEvent::PlayerEventContainer{}; + auto s = reinterpret_cast(pack->pBuffer); + EQ::Util::MemoryStreamReader ss(s->cereal_data, s->cereal_size); + cereal::BinaryInputArchive archive(ss); + archive(n); + + player_event_logs.AddToQueue(n.player_event_log); + + discord_manager.QueuePlayerEventMessage(n); + break; + } + default: { + LogInfo("Unknown ServerOP Received [{}]", opcode); + break; + } + } +} diff --git a/queryserv/zoneserver.h b/queryserv/zoneserver.h new file mode 100644 index 000000000..db36bd4ff --- /dev/null +++ b/queryserv/zoneserver.h @@ -0,0 +1,32 @@ +#ifndef ZONESERVER_H +#define ZONESERVER_H + +#include "../world/world_tcp_connection.h" +#include "../common/net/servertalk_server.h" +#include "../common/event/timer.h" +#include "../common/timer.h" +#include "../common/emu_constants.h" +#include "../world/console.h" +#include + +class Client; +class ServerPacket; + +class ZoneServer : public WorldTCPConnection { +public: + ZoneServer(std::shared_ptr in_connection, EQ::Net::ConsoleServer *in_console); + ~ZoneServer(); + void SendPacket(ServerPacket *pack) { m_connection->SendPacket(pack); } + void SetIsZoneConnected(bool in) { m_is_zone_connected = in; } + bool GetIsZoneConnected() { return m_is_zone_connected; } + void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); + std::string GetUUID() const { return m_connection->GetUUID(); } + +private: + std::shared_ptr m_connection{}; + bool m_is_zone_connected = false; + EQ::Net::ConsoleServer *m_console; +}; + +#endif + diff --git a/utils/sql/git/optional/2025_01_09_drop_qs_tables.sql b/utils/sql/git/optional/2025_01_09_drop_qs_tables.sql new file mode 100644 index 000000000..7117d8e55 --- /dev/null +++ b/utils/sql/git/optional/2025_01_09_drop_qs_tables.sql @@ -0,0 +1,17 @@ +-- Drop all qs_ tables +DROP TABLE IF EXISTS + qs_merchant_transaction_record, + qs_merchant_transaction_record_entries, + qs_player_aa_rate_hourly, + qs_player_delete_record, + qs_player_delete_record_entries, + qs_player_events, + qs_player_handin_record, + qs_player_handin_record_entries, + qs_player_move_record, + qs_player_move_record_entries, + qs_player_npc_kill_record, + qs_player_npc_kill_record_entries, + qs_player_speech, + qs_player_trade_record, + qs_player_trade_record_entries; diff --git a/utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql b/utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql new file mode 100644 index 000000000..dc808bca9 --- /dev/null +++ b/utils/sql/git/optional/2025_01_09_qs_to_player_event_convert.sql @@ -0,0 +1,94 @@ +-- ================================ +-- Conversion of Merchant Transactions +-- ================================ +INSERT INTO player_event_merchant_sell ( + npc_id, merchant_name, merchant_type, item_id, item_name, charges, cost, alternate_currency_id, + player_money_balance, player_currency_balance, created_at +) +SELECT + r.merchant_id, NULL AS merchant_name, NULL AS merchant_type, e.item_id, NULL AS item_name, e.charges, r.merchant_cp AS cost, NULL AS alternate_currency_id, + r.char_cp AS player_money_balance, NULL AS player_currency_balance, r.time AS created_at +FROM qs_merchant_transaction_record AS r + JOIN qs_merchant_transaction_record_entries AS e + ON r.transaction_id = e.event_id; + +-- ================================ +-- Conversion of Player Trades +-- ================================ +INSERT INTO player_event_trade ( + char1_id, char2_id, char1_copper, char1_silver, char1_gold, char1_platinum, + char2_copper, char2_silver, char2_gold, char2_platinum, created_at +) +SELECT + char1_id, char2_id, char1_cp, char1_sp, char1_gp, char1_pp, + char2_cp, char2_sp, char2_gp, char2_pp, time AS created_at +FROM qs_player_trade_record; + +INSERT INTO player_event_trade_entries ( + player_event_trade_id, char_id, slot, item_id, charges, augment_1_id, augment_2_id, augment_3_id, + augment_4_id, augment_5_id, augment_6_id, in_bag, created_at +) +SELECT + event_id, from_id AS char_id, from_slot AS slot, item_id, charges, aug_1 AS augment_1_id, aug_2 AS augment_2_id, aug_3 AS augment_3_id, + aug_4 AS augment_4_id, aug_5 AS augment_5_id, NULL AS augment_6_id, 0 AS in_bag, NULL AS created_at +FROM qs_player_trade_record_entries; + +-- ================================ +-- Conversion of NPC Hand-ins +-- ================================ +INSERT INTO player_event_npc_handin ( + npc_id, npc_name, handin_copper, handin_silver, handin_gold, handin_platinum, + return_copper, return_silver, return_gold, return_platinum, is_quest_handin, created_at +) +SELECT + npc_id, NULL AS npc_name, char_cp AS handin_copper, char_sp AS handin_silver, char_gp AS handin_gold, char_pp AS handin_platinum, + npc_cp AS return_copper, npc_sp AS return_silver, npc_gp AS return_gold, npc_pp AS return_platinum, + 0 AS is_quest_handin, time AS created_at +FROM qs_player_handin_record; + +INSERT INTO player_event_npc_handin_entries ( + player_event_npc_handin_id, type, item_id, charges, evolve_level, evolve_amount, + augment_1_id, augment_2_id, augment_3_id, augment_4_id, augment_5_id, augment_6_id, created_at +) +SELECT + event_id, NULL AS type, item_id, charges, 0 AS evolve_level, 0 AS evolve_amount, + aug_1 AS augment_1_id, aug_2 AS augment_2_id, aug_3 AS augment_3_id, aug_4 AS augment_4_id, aug_5 AS augment_5_id, 0 AS augment_6_id, NULL AS created_at +FROM qs_player_handin_record_entries; + +-- ================================ +-- Conversion of NPC Kill Records +-- ================================ +INSERT INTO player_event_killed_npc ( + npc_id, npc_name, combat_time_seconds, total_damage_per_second_taken, total_heal_per_second_taken, created_at +) +SELECT + npc_id, NULL AS npc_name, NULL AS combat_time_seconds, NULL AS total_damage_per_second_taken, NULL AS total_heal_per_second_taken, time AS created_at +FROM qs_player_npc_kill_record; + +INSERT INTO player_event_killed_named_npc ( + npc_id, npc_name, combat_time_seconds, total_damage_per_second_taken, total_heal_per_second_taken, created_at +) +SELECT + npc_id, NULL AS npc_name, NULL AS combat_time_seconds, NULL AS total_damage_per_second_taken, NULL AS total_heal_per_second_taken, time AS created_at +FROM qs_player_npc_kill_record WHERE type = 1; -- Example condition for named NPCs + +-- ================================ +-- Conversion of Player Speech +-- ================================ +INSERT INTO player_event_speech ( + from_char_id, to_char_id, guild_id, type, min_status, message, created_at +) +SELECT + `from` AS from_char_id, `to` AS to_char_id, guilddbid AS guild_id, type, minstatus AS min_status, message, + timerecorded AS created_at +FROM qs_player_speech; + +-- ================================ +-- Conversion of AA Purchases +-- ================================ +INSERT INTO player_event_aa_purchase ( + aa_ability_id, cost, previous_id, next_id, created_at +) +SELECT + NULL AS aa_ability_id, NULL AS cost, NULL AS previous_id, NULL AS next_id, NULL AS created_at +FROM qs_player_aa_rate_hourly; -- Adjust as necessary for the source table and logic diff --git a/utils/sql/svn/2268_QueryServ.sql b/utils/sql/svn/2268_QueryServ.sql deleted file mode 100644 index 95b7232ac..000000000 --- a/utils/sql/svn/2268_QueryServ.sql +++ /dev/null @@ -1,22 +0,0 @@ -SET FOREIGN_KEY_CHECKS=0; --- ---------------------------- --- Table structure for `qs_player_npc_kill_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_npc_kill_record`; -CREATE TABLE `qs_player_npc_kill_record` ( - `fight_id` int(11) NOT NULL AUTO_INCREMENT, - `npc_id` int(11) DEFAULT NULL, - `type` int(11) DEFAULT NULL, - `zone_id` int(11) DEFAULT NULL, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`fight_id`) -) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_npc_kill_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_npc_kill_record_entries`; -CREATE TABLE `qs_player_npc_kill_record_entries` ( - `event_id` int(11) DEFAULT '0', - `char_id` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/utils/sql/svn/2304_QueryServ.sql b/utils/sql/svn/2304_QueryServ.sql deleted file mode 100644 index 6f2c158c5..000000000 --- a/utils/sql/svn/2304_QueryServ.sql +++ /dev/null @@ -1,41 +0,0 @@ -SET FOREIGN_KEY_CHECKS=0; --- ---------------------------- --- Table structure for `qs_player_npc_kill_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_trade_record`; -CREATE TABLE `qs_player_trade_record` ( - `trade_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `char1_id` int(11) DEFAULT '0', - `char1_pp` int(11) DEFAULT '0', - `char1_gp` int(11) DEFAULT '0', - `char1_sp` int(11) DEFAULT '0', - `char1_cp` int(11) DEFAULT '0', - `char1_items` mediumint(7) DEFAULT '0', - `char2_id` int(11) DEFAULT '0', - `char2_pp` int(11) DEFAULT '0', - `char2_gp` int(11) DEFAULT '0', - `char2_sp` int(11) DEFAULT '0', - `char2_cp` int(11) DEFAULT '0', - `char2_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`trade_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_npc_kill_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_trade_record_entries`; -CREATE TABLE `qs_player_trade_record_entries` ( - `event_id` int(11) DEFAULT '0', - `from_id` int(11) DEFAULT '0', - `from_slot` mediumint(7) DEFAULT '0', - `to_id` int(11) DEFAULT '0', - `to_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/utils/sql/svn/2361_QueryServ.sql b/utils/sql/svn/2361_QueryServ.sql deleted file mode 100644 index faa195a32..000000000 --- a/utils/sql/svn/2361_QueryServ.sql +++ /dev/null @@ -1,141 +0,0 @@ -SET FOREIGN_KEY_CHECKS=0; --- ---------------------------- --- Table structure for `qs_merchant_transaction_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_merchant_transaction_record`; -CREATE TABLE `qs_merchant_transaction_record` ( - `transaction_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `zone_id` int(11) DEFAULT '0', - `merchant_id` int(11) DEFAULT '0', - `merchant_pp` int(11) DEFAULT '0', - `merchant_gp` int(11) DEFAULT '0', - `merchant_sp` int(11) DEFAULT '0', - `merchant_cp` int(11) DEFAULT '0', - `merchant_items` mediumint(7) DEFAULT '0', - `char_id` int(11) DEFAULT '0', - `char_pp` int(11) DEFAULT '0', - `char_gp` int(11) DEFAULT '0', - `char_sp` int(11) DEFAULT '0', - `char_cp` int(11) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`transaction_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_merchant_transaction_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_merchant_transaction_record_entries`; -CREATE TABLE `qs_merchant_transaction_record_entries` ( - `event_id` int(11) DEFAULT '0', - `char_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_delete_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_delete_record`; -CREATE TABLE `qs_player_delete_record` ( - `delete_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `char_id` int(11) DEFAULT '0', - `stack_size` mediumint(7) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`delete_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_delete_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_delete_record_entries`; -CREATE TABLE `qs_player_delete_record_entries` ( - `event_id` int(11) DEFAULT '0', - `char_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_handin_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_handin_record`; -CREATE TABLE `qs_player_handin_record` ( - `handin_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `quest_id` int(11) DEFAULT '0', - `char_id` int(11) DEFAULT '0', - `char_pp` int(11) DEFAULT '0', - `char_gp` int(11) DEFAULT '0', - `char_sp` int(11) DEFAULT '0', - `char_cp` int(11) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - `npc_id` int(11) DEFAULT '0', - `npc_pp` int(11) DEFAULT '0', - `npc_gp` int(11) DEFAULT '0', - `npc_sp` int(11) DEFAULT '0', - `npc_cp` int(11) DEFAULT '0', - `npc_items` mediumint(7) DEFAULT '0', - PRIMARY KEY (`handin_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_handin_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_handin_record_entries`; -CREATE TABLE `qs_player_handin_record_entries` ( - `event_id` int(11) DEFAULT '0', - `action_type` char(6) Default 'action', - `char_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_move_record` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_move_record`; -CREATE TABLE `qs_player_move_record` ( - `move_id` int(11) NOT NULL AUTO_INCREMENT, - `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `char_id` int(11) DEFAULT '0', - `from_slot` mediumint(7) DEFAULT '0', - `to_slot` mediumint(7) DEFAULT '0', - `stack_size` mediumint(7) DEFAULT '0', - `char_items` mediumint(7) DEFAULT '0', - `postaction` tinyint(1) DEFAULT '0', - PRIMARY KEY (`move_id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; - --- ---------------------------- --- Table structure for `qs_player_move_record_entries` --- ---------------------------- -DROP TABLE IF EXISTS `qs_player_move_record_entries`; -CREATE TABLE `qs_player_move_record_entries` ( - `event_id` int(11) DEFAULT '0', - `from_slot` mediumint(7) DEFAULT '0', - `to_slot` mediumint(7) DEFAULT '0', - `item_id` int(11) DEFAULT '0', - `charges` mediumint(7) DEFAULT '0', - `aug_1` int(11) DEFAULT '0', - `aug_2` int(11) DEFAULT '0', - `aug_3` int(11) DEFAULT '0', - `aug_4` int(11) DEFAULT '0', - `aug_5` int(11) DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/world/cli/database_dump.cpp b/world/cli/database_dump.cpp index e9068d63b..67a591fb0 100644 --- a/world/cli/database_dump.cpp +++ b/world/cli/database_dump.cpp @@ -14,7 +14,6 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std: "--merc-tables", "--state-tables", "--system-tables", - "--query-serv-tables", "--static-instance-data", "--table-structure-only", "--table-lock", @@ -45,7 +44,6 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std: s->SetDumpMercTables(cmd[{"--merc-tables"}] || dump_all); s->SetDumpStateTables(cmd[{"--state-tables"}] || dump_all); s->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all); - s->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all); s->SetDumpAllTables(dump_all); s->SetDumpWithNoData(cmd[{"--table-structure-only"}]); s->SetDumpTableLock(cmd[{"--table-lock"}]); diff --git a/world/cli/etl_get_settings.cpp b/world/cli/etl_get_settings.cpp new file mode 100644 index 000000000..6af88cd46 --- /dev/null +++ b/world/cli/etl_get_settings.cpp @@ -0,0 +1,41 @@ +#include "../../common/events/player_event_logs.h" +#include "../../common/json/json.h" + +void WorldserverCLI::EtlGetSettings(int argc, char **argv, argh::parser &cmd, std::string &description) +{ + description = "Displays server player event logs that are etl enabled"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + Json::Value etl_settings; + Json::Value player_events; + + player_event_logs.SetDatabase(&database)->Init(); + auto event_settings = player_event_logs.GetSettings(); + auto etl_details = player_event_logs.GetEtlSettings(); + + for (auto i = 0; i < PlayerEvent::EventType::MAX; i++) { + player_events["event_id"] = event_settings[i].id; + player_events["enabled"] = event_settings[i].event_enabled ? true : false; + player_events["retention"] = event_settings[i].retention_days; + player_events["discord_id"] = event_settings[i].discord_webhook_id; + player_events["etl_enabled"] = event_settings[i].etl_enabled ? true : false; + player_events["table_name"] = ""; + + auto it = etl_details.find(static_cast(event_settings[i].id)); + + if (it != std::end(etl_details)) { + player_events["table_name"] = it->second.table_name; + player_events["etl_enabled"] = it->second.enabled; + } + + etl_settings["etl_settings"].append(player_events); + } + + std::stringstream payload; + payload << etl_settings; + + std::cout << payload.str() << std::endl; +} diff --git a/world/eqemu_api_world_data_service.cpp b/world/eqemu_api_world_data_service.cpp index bfa7f6a1b..12f7193d5 100644 --- a/world/eqemu_api_world_data_service.cpp +++ b/world/eqemu_api_world_data_service.cpp @@ -1,23 +1,3 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY except by those people which sell it, which - * are required to give you total support for your newly bought product; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - #include #include "clientlist.h" #include "cliententry.h" @@ -29,10 +9,14 @@ #include "worlddb.h" #include "wguild_mgr.h" #include "world_config.h" +#include "ucs.h" +#include "queryserv.h" extern ZSList zoneserver_list; extern ClientList client_list; extern WorldGuildManager guild_mgr; +extern UCSConnection UCSLink; +extern QueryServConnection QSLink; void callGetZoneList(Json::Value &response) { @@ -237,6 +221,8 @@ void EQEmuApiWorldDataService::reload(Json::Value &r, const std::vectorLoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true); diff --git a/world/main.cpp b/world/main.cpp index 71109bb95..2b4a2c8f4 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -376,7 +376,9 @@ int main(int argc, char **argv) ); Timer player_event_process_timer(1000); - player_event_logs.SetDatabase(&database)->Init(); + if (player_event_logs.LoadDatabaseConnection()) { + player_event_logs.Init(); + } auto loop_fn = [&](EQ::Timer* t) { Timer::SetCurrentTime(); @@ -441,7 +443,7 @@ int main(int argc, char **argv) } if (player_event_process_timer.Check()) { - player_event_logs.Process(); + std::jthread event_thread(&PlayerEventLogs::Process, &player_event_logs); } if (PurgeInstanceTimer.Check()) { diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp index 973374c01..3af88f953 100644 --- a/world/world_server_cli.cpp +++ b/world/world_server_cli.cpp @@ -34,6 +34,7 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) function_map["test:repository2"] = &WorldserverCLI::TestRepository2; function_map["test:db-concurrency"] = &WorldserverCLI::TestDatabaseConcurrency; function_map["test:string-benchmark"] = &WorldserverCLI::TestStringBenchmarkCommand; + function_map["etl:settings"] = &WorldserverCLI::EtlGetSettings; EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } @@ -56,3 +57,4 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) #include "cli/test_repository_2.cpp" #include "cli/test_string_benchmark.cpp" #include "cli/version.cpp" +#include "cli/etl_get_settings.cpp" diff --git a/world/world_server_cli.h b/world/world_server_cli.h index 0edebd261..1066158b9 100644 --- a/world/world_server_cli.h +++ b/world/world_server_cli.h @@ -25,6 +25,7 @@ public: static void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestDatabaseConcurrency(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestStringBenchmarkCommand(int argc, char **argv, argh::parser &cmd, std::string &description); + static void EtlGetSettings(int argc, char **argv, argh::parser &cmd, std::string &description); }; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 25f6fdbd8..554075e83 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1353,15 +1353,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { safe_delete(outapp); break; } - case ServerOP_Speech: - case ServerOP_QSSendQuery: - case ServerOP_QSPlayerLogDeletes: - case ServerOP_QSPlayerDropItem: - case ServerOP_QSPlayerLogHandins: - case ServerOP_QSPlayerLogMerchantTransactions: - case ServerOP_QSPlayerLogMoves: - case ServerOP_QSPlayerLogNPCKills: - case ServerOP_QSPlayerLogTrades: case ServerOP_QueryServGeneric: { QSLink.SendPacket(pack); break; @@ -1481,6 +1472,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { } case ServerOP_ReloadLogs: { zoneserver_list.SendPacket(pack); + QSLink.SendPacket(pack); UCSLink.SendPacket(pack); LogSys.LoadLogDatabaseSettings(); player_event_logs.ReloadSettings(); diff --git a/zone/aa.cpp b/zone/aa.cpp index d75001d18..b147c566f 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1202,19 +1202,6 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str() ); } - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)) { - const auto event_desc = fmt::format( - "Ranked AA Purchase :: aa_id:{} at cost:{} in zoneid:{} instid:{}", - rank->id, - cost, - GetZoneID(), - GetInstanceID() - ); - - QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); - } } else { if (send_message_and_save) { MessageString( @@ -1225,19 +1212,6 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str() ); } - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)) { - const auto event_desc = fmt::format( - "Initial AA Purchase :: aa_id:{} at cost:{} in zoneid:{} instid:{}", - rank->id, - cost, - GetZoneID(), - GetInstanceID() - ); - - QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); - } } if (parse->PlayerHasQuestSub(EVENT_AA_BUY)) { diff --git a/zone/attack.cpp b/zone/attack.cpp index 5a01cf53c..8f6aaf02d 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2163,14 +2163,6 @@ bool Client::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::Skil GoToDeath(); } - /* QS: PlayerLogDeaths */ - if (RuleB(QueryServ, PlayerLogDeaths)) { - const char * killer_name = ""; - if (killer_mob && killer_mob->GetCleanName()) { killer_name = killer_mob->GetCleanName(); } - std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", GetZoneID(), GetInstanceID(), killer_name, spell, damage); - QServ->PlayerLogEvent(Player_Log_Deaths, CharacterID(), event_desc); - } - if (player_event_logs.IsEventEnabled(PlayerEvent::DEATH)) { auto e = PlayerEvent::DeathEvent{ .killer_id = killer_mob ? static_cast(killer_mob->GetID()) : static_cast(0), @@ -2723,37 +2715,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy player_count++; } } - - // QueryServ Logging - Raid Kills - if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket( - ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * player_count) - ); - - player_count = 0; - - auto QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 2; // Raid Fight - - for (const auto& m : killer_raid->members) { - if (m.is_bot) { - continue; - } - - if (m.member && m.member->IsClient()) { - QS->Chars[player_count].char_id = m.member->CastToClient()->CharacterID(); - player_count++; - } - } - - worldserver.SendPacket(pack); - safe_delete(pack); - } } else if (give_exp_client->IsGrouped() && killer_group) { if (!is_ldon_treasure && MerchantType == 0) { killer_group->SplitExp(ExpSource::Kill, final_exp, this); @@ -2787,33 +2748,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy player_count++; } } - - // QueryServ Logging - Group Kills - if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket( - ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * player_count) - ); - - player_count = 0; - - auto QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 1; // Group Fight - - for (const auto& m : killer_group->members) { - if (m && m->IsClient()) { - QS->Chars[player_count].char_id = m->CastToClient()->CharacterID(); - player_count++; - } - } - - worldserver.SendPacket(pack); - safe_delete(pack); - } } else { if (!is_ldon_treasure && !MerchantType) { const uint32 con_level = give_exp->GetLevelCon(GetLevel()); @@ -2844,28 +2778,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy give_exp_client->GetDeity() ); } - - // QueryServ Logging - Solo - if (RuleB(QueryServ, PlayerLogNPCKills)) { - auto pack = new ServerPacket( - ServerOP_QSPlayerLogNPCKills, - sizeof(QSPlayerLogNPCKill_Struct) + - (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1) - ); - - auto QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - - QS->s1.NPCID = GetNPCTypeID(); - QS->s1.ZoneID = GetZoneID(); - QS->s1.Type = 0; // Solo Fight - QS->Chars[0].char_id = give_exp_client->CharacterID(); - - player_count++; - - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging } } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index cd82dba6f..007ea1127 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -367,12 +367,6 @@ int bot_command_real_dispatch(Client *c, const char *message) return(-1); } - /* QS: Player_Log_Issued_Commands */ - if (RuleB(QueryServ, PlayerLogIssuedCommandes)){ - std::string event_desc = StringFormat("Issued bot command :: '%s' in zoneid:%i instid:%i", message, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); - } - if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) { LogCommands("[{}] ([{}]) used bot command: [{}] (target=[{}])", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE"); } diff --git a/zone/cheat_manager.cpp b/zone/cheat_manager.cpp index 5a84dc09d..2d4696658 100644 --- a/zone/cheat_manager.cpp +++ b/zone/cheat_manager.cpp @@ -3,8 +3,10 @@ #include "quest_parser_collection.h" #include "../common/events/player_event_logs.h" #include "worldserver.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; void CheatManager::SetClient(Client *cli) { diff --git a/zone/client.cpp b/zone/client.cpp index 8a1ac19e6..9d87a8828 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1247,28 +1247,21 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } } - /* Logs Player Chat */ - if (RuleB(QueryServ, PlayerLogChat)) { - auto pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1); - Server_Speech_Struct* sem = (Server_Speech_Struct*) pack->pBuffer; + if (player_event_logs.IsEventEnabled(PlayerEvent::EventType::SPEECH)) { + PlayerEvent::PlayerSpeech e{}; + std::string msg = message; + if (!msg.empty() && msg.at(0) != '#' && msg.at(0) != '^') { + e.message = message; + e.min_status = Admin(); + e.type = chan_num; + e.to = targetname; + e.from = GetCleanName(); + if (chan_num == ChatChannel_Guild) { + e.guild_id = GuildID(); + } - if(chan_num == ChatChannel_Guild) - sem->guilddbid = GuildID(); - else - sem->guilddbid = 0; - - strcpy(sem->message, message); - sem->minstatus = Admin(); - sem->type = chan_num; - if(targetname != 0) - strcpy(sem->to, targetname); - - if(GetName() != 0) - strcpy(sem->from, GetName()); - - if(worldserver.Connected()) - worldserver.SendPacket(pack); - safe_delete(pack); + RecordPlayerEventLog(PlayerEvent::SPEECH, e); + } } // Garble the message based on drunkness @@ -7218,15 +7211,6 @@ int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_sc return 0; } - /* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */ - if (is_scripted) { - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } - } - if (!amount) { return 0; } @@ -12557,23 +12541,22 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) if (inst) { t_entries.emplace_back( PlayerEvent::TradeItemEntry{ - .slot = i, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = false, + .slot = i, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "",.item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = false, } ); @@ -12581,27 +12564,26 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { - t_entries.emplace_back( - PlayerEvent::TradeItemEntry{ - .slot = j, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = true, - } - ); + t_entries.emplace_back(PlayerEvent::TradeItemEntry{ + .slot = j, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = true, + } + ); } } } @@ -12615,52 +12597,50 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) for (uint16 i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_END; i++) { const EQ::ItemInstance *inst = trader2->GetInv().GetItem(i); if (inst) { - t2_entries.emplace_back( - PlayerEvent::TradeItemEntry{ - .slot = i, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = false, - } + t2_entries.emplace_back(PlayerEvent::TradeItemEntry{ + .slot = i, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = false, + } ); if (inst->IsClassBag()) { for (uint8 j = EQ::invbag::SLOT_BEGIN; j <= EQ::invbag::SLOT_END; j++) { inst = trader2->GetInv().GetItem(i, j); if (inst) { - t2_entries.emplace_back( - PlayerEvent::TradeItemEntry{ - .slot = j, - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = static_cast(inst->GetCharges()), - .aug_1_item_id = inst->GetAugmentItemID(0), - .aug_1_item_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", - .aug_2_item_id = inst->GetAugmentItemID(1), - .aug_2_item_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", - .aug_3_item_id = inst->GetAugmentItemID(2), - .aug_3_item_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", - .aug_4_item_id = inst->GetAugmentItemID(3), - .aug_4_item_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", - .aug_5_item_id = inst->GetAugmentItemID(4), - .aug_5_item_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", - .aug_6_item_id = inst->GetAugmentItemID(5), - .aug_6_item_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", - .in_bag = true, - } + t2_entries.emplace_back(PlayerEvent::TradeItemEntry{ + .slot = j, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_1_name = inst->GetAugment(0) ? inst->GetAugment(0)->GetItem()->Name : "", + .augment_2_id = inst->GetAugmentItemID(1), + .augment_2_name = inst->GetAugment(1) ? inst->GetAugment(1)->GetItem()->Name : "", + .augment_3_id = inst->GetAugmentItemID(2), + .augment_3_name = inst->GetAugment(2) ? inst->GetAugment(2)->GetItem()->Name : "", + .augment_4_id = inst->GetAugmentItemID(3), + .augment_4_name = inst->GetAugment(3) ? inst->GetAugment(3)->GetItem()->Name : "", + .augment_5_id = inst->GetAugmentItemID(4), + .augment_5_name = inst->GetAugment(4) ? inst->GetAugment(4)->GetItem()->Name : "", + .augment_6_id = inst->GetAugmentItemID(5), + .augment_6_name = inst->GetAugment(5) ? inst->GetAugment(5)->GetItem()->Name : "", + .item_name = inst->GetItem()->Name, + .charges = static_cast(inst->GetCharges()), + .in_bag = true, + } ); } } @@ -12681,6 +12661,7 @@ void Client::PlayerTradeEventLog(Trade *t, Trade *t2) }; RecordPlayerEventLogWithClient(trader, PlayerEvent::TRADE, e); + //Not sure the usefulness of sending the same data twice?? RecordPlayerEventLogWithClient(trader2, PlayerEvent::TRADE, e); } diff --git a/zone/client.h b/zone/client.h index 8f7b44d8a..9d576b5ef 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1124,7 +1124,6 @@ public: void RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity = 1); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); - void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, LootItem** bag_item_data = 0); bool AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, LootItem** bag_item_data = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQ::invslot::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); @@ -1133,7 +1132,6 @@ public: void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id, bool recurse = true); - void DropItemQS(EQ::ItemInstance* inst, bool pickup); bool HasItemOnCorpse(uint32 item_id); bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction); diff --git a/zone/client_evolving_items.cpp b/zone/client_evolving_items.cpp index 4fb2238b0..f94667797 100644 --- a/zone/client_evolving_items.cpp +++ b/zone/client_evolving_items.cpp @@ -8,6 +8,7 @@ #include "worldserver.h" extern WorldServer worldserver; +extern QueryServ* QServ; void Client::DoEvolveItemToggle(const EQApplicationPacket *app) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 901b16d40..3751503de 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -811,12 +811,6 @@ void Client::CompleteConnect() parse->EventPlayer(EVENT_CONNECT, this, "", 0); } - /* QS: PlayerLogConnectDisconnect */ - if (RuleB(QueryServ, PlayerLogConnectDisconnect)) { - std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Connect_State, CharacterID(), event_desc); - } - /** * Update last login since this doesn't get updated until a late save later so we can update online status */ @@ -2676,12 +2670,6 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - /* QS: PlayerLogAlternateCurrencyTransactions :: Merchant Purchase */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Merchant Purchase :: Spent alt_currency_id:%i cost:%i for itemid:%i in zoneid:%i instid:%i", alt_cur_id, cost, item->ID, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } - if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_MERCHANT_BUY)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -2767,12 +2755,6 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) uint32 removed = NukeItem(item_id, invWhereWorn | invWherePersonal | invWhereCursor); if (removed > 0) { AddAlternateCurrencyValue(reclaim->currency_id, removed); - - /* QS: PlayerLogAlternateCurrencyTransactions :: Item to Currency */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Reclaim :: Item to Currency :: alt_currency_id:%i amount:%i to currency tab in zoneid:%i instid:%i", reclaim->currency_id, removed, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } } } /* Cursor to Item storage */ @@ -2791,11 +2773,6 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor); AddAlternateCurrencyValue(reclaim->currency_id, -((int)reclaim->count)); } - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Reclaim :: Cursor to Item :: alt_currency_id:%i amount:-%i in zoneid:%i instid:%i", reclaim->currency_id, reclaim->count, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } } } @@ -2894,12 +2871,6 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) sell->cost = cost; - /* QS: PlayerLogAlternateCurrencyTransactions :: Sold to Merchant*/ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { - std::string event_desc = StringFormat("Sold to Merchant :: itemid:%u npcid:%u alt_currency_id:%u cost:%u in zoneid:%u instid:%i", item->ID, npc_id, alt_cur_id, cost, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, CharacterID(), event_desc); - } - if (parse->PlayerHasQuestSub(EVENT_ALT_CURRENCY_MERCHANT_SELL)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -5699,10 +5670,17 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY) && inst->GetItem()) { auto e = PlayerEvent::DestroyItemEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .reason = "Client deleted", + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .attuned = inst->IsAttuned(), + .reason = "Client deleted" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -13991,8 +13969,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) sizeof(Merchant_Sell_Struct), app->size); return; } - RDTSC_Timer t1; - t1.start(); + Merchant_Sell_Struct* mp = (Merchant_Sell_Struct*)app->pBuffer; #if EQDEBUG >= 5 LogDebug("[{}], purchase item", GetName()); @@ -14193,8 +14170,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) SendItemPacket(mp->itemslot, inst, ItemPacketMerchant); } } - safe_delete(inst); - safe_delete(outapp); if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { auto e = PlayerEvent::MerchantPurchaseEvent{ @@ -14213,61 +14188,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); } - // start QS code - // stacking purchases not supported at this time - entire process will need some work to catch them properly - if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - auto qspack = - new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, - sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct)); - QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; - - qsaudit->zone_id = zone->GetZoneID(); - qsaudit->merchant_id = tmp->CastToNPC()->MerchantType; - qsaudit->merchant_money.platinum = 0; - qsaudit->merchant_money.gold = 0; - qsaudit->merchant_money.silver = 0; - qsaudit->merchant_money.copper = 0; - qsaudit->merchant_count = 1; - qsaudit->char_id = character_id; - qsaudit->char_money.platinum = (mpo->price / 1000); - qsaudit->char_money.gold = (mpo->price / 100) % 10; - qsaudit->char_money.silver = (mpo->price / 10) % 10; - qsaudit->char_money.copper = mpo->price % 10; - qsaudit->char_count = 0; - - qsaudit->items[0].char_slot = freeslotid == INVALID_INDEX ? 0 : freeslotid; - qsaudit->items[0].item_id = item->ID; - qsaudit->items[0].charges = mpo->quantity; - - const EQ::ItemInstance* audit_inst = m_inv[freeslotid]; - - if (audit_inst) { - qsaudit->items[0].aug_1 = audit_inst->GetAugmentItemID(0); - qsaudit->items[0].aug_2 = audit_inst->GetAugmentItemID(1); - qsaudit->items[0].aug_3 = audit_inst->GetAugmentItemID(2); - qsaudit->items[0].aug_4 = audit_inst->GetAugmentItemID(3); - qsaudit->items[0].aug_5 = audit_inst->GetAugmentItemID(4); - } - else { - qsaudit->items[0].aug_1 = 0; - qsaudit->items[0].aug_2 = 0; - qsaudit->items[0].aug_3 = 0; - qsaudit->items[0].aug_4 = 0; - qsaudit->items[0].aug_5 = 0; - - if (freeslotid != INVALID_INDEX) { - LogError("Handle_OP_ShopPlayerBuy: QS Audit could not locate merchant ([{}]) purchased item in player ([{}]) inventory slot ([{}])", - qsaudit->merchant_id, qsaudit->char_id, freeslotid); - } - } - - audit_inst = nullptr; - - if (worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - if (parse->PlayerHasQuestSub(EVENT_MERCHANT_BUY)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -14281,23 +14201,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) parse->EventPlayer(EVENT_MERCHANT_BUY, this, export_string, 0); } - if (player_event_logs.IsEventEnabled(PlayerEvent::MERCHANT_PURCHASE)) { - auto e = PlayerEvent::MerchantPurchaseEvent{ - .npc_id = tmp->GetNPCTypeID(), - .merchant_name = tmp->GetCleanName(), - .merchant_type = tmp->CastToNPC()->MerchantType, - .item_id = item->ID, - .item_name = item->Name, - .charges = static_cast(mpo->quantity), - .cost = mpo->price, - .alternate_currency_id = 0, - .player_money_balance = GetCarriedMoney(), - .player_currency_balance = 0, - }; - RecordPlayerEventLog(PlayerEvent::MERCHANT_PURCHASE, e); - } - - if (RuleB(Character, EnableDiscoveredItems) && !IsDiscovered(item_id)) { if (!GetGM()) { DiscoverItem(item_id); @@ -14313,9 +14216,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) } } - t1.stop(); - std::cout << "At 1: " << t1.getDuration() << std::endl; - return; + safe_delete(inst); + safe_delete(outapp); } void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) { @@ -14453,41 +14355,6 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } } - // start QS code - if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - auto qspack = - new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, - sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct)); - QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; - - qsaudit->zone_id = zone->GetZoneID(); - qsaudit->merchant_id = vendor->CastToNPC()->MerchantType; - qsaudit->merchant_money.platinum = (price / 1000); - qsaudit->merchant_money.gold = (price / 100) % 10; - qsaudit->merchant_money.silver = (price / 10) % 10; - qsaudit->merchant_money.copper = price % 10; - qsaudit->merchant_count = 0; - qsaudit->char_id = character_id; - qsaudit->char_money.platinum = 0; - qsaudit->char_money.gold = 0; - qsaudit->char_money.silver = 0; - qsaudit->char_money.copper = 0; - qsaudit->char_count = 1; - - qsaudit->items[0].char_slot = mp->itemslot; - qsaudit->items[0].item_id = itemid; - qsaudit->items[0].charges = charges; - qsaudit->items[0].aug_1 = m_inv[mp->itemslot]->GetAugmentItemID(1); - qsaudit->items[0].aug_2 = m_inv[mp->itemslot]->GetAugmentItemID(2); - qsaudit->items[0].aug_3 = m_inv[mp->itemslot]->GetAugmentItemID(3); - qsaudit->items[0].aug_4 = m_inv[mp->itemslot]->GetAugmentItemID(4); - qsaudit->items[0].aug_5 = m_inv[mp->itemslot]->GetAugmentItemID(5); - - if (worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - if (parse->PlayerHasQuestSub(EVENT_MERCHANT_SELL)) { const auto& export_string = fmt::format( "{} {} {} {} {}", @@ -15425,48 +15292,8 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) else { other->PlayerTradeEventLog(other->trade, trade); - // start QS code - if (RuleB(QueryServ, PlayerLogTrades)) { - PlayerLogTrade_Struct event_entry; - std::list event_details; - - memset(&event_entry, 0, sizeof(PlayerLogTrade_Struct)); - - // Perform actual trade - FinishTrade(other, true, &event_entry, &event_details); - other->FinishTrade(this, false, &event_entry, &event_details); - - event_entry._detail_count = event_details.size(); - - auto qs_pack = new ServerPacket( - ServerOP_QSPlayerLogTrades, - sizeof(PlayerLogTrade_Struct) + - (sizeof(PlayerLogTradeItemsEntry_Struct) * event_entry._detail_count)); - PlayerLogTrade_Struct* qs_buf = (PlayerLogTrade_Struct*)qs_pack->pBuffer; - - memcpy(qs_buf, &event_entry, sizeof(PlayerLogTrade_Struct)); - - int offset = 0; - - for (auto iter = event_details.begin(); iter != event_details.end(); - ++iter, ++offset) { - PlayerLogTradeItemsEntry_Struct* detail = reinterpret_cast(*iter); - qs_buf->item_entries[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - // end QS code - } - else { - FinishTrade(other); - other->FinishTrade(this); - } + FinishTrade(other); + other->FinishTrade(this); other->trade->Reset(); trade->Reset(); @@ -15483,43 +15310,7 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) QueuePacket(outapp); safe_delete(outapp); if (with->IsNPC()) { - // Audit trade to database for player trade stream - if (RuleB(QueryServ, PlayerLogHandins)) { - QSPlayerLogHandin_Struct event_entry; - std::list event_details; - - memset(&event_entry, 0, sizeof(QSPlayerLogHandin_Struct)); - - FinishTrade(with->CastToNPC(), false, &event_entry, &event_details); - - event_entry._detail_count = event_details.size(); - - auto qs_pack = - new ServerPacket(ServerOP_QSPlayerLogHandins, - sizeof(QSPlayerLogHandin_Struct) + - (sizeof(QSHandinItems_Struct) * event_entry._detail_count)); - QSPlayerLogHandin_Struct* qs_buf = (QSPlayerLogHandin_Struct*)qs_pack->pBuffer; - - memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogHandin_Struct)); - - int offset = 0; - - for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSHandinItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - } - else { - FinishTrade(with->CastToNPC()); - } + FinishTrade(with->CastToNPC()); } // TODO: Log Bot trades else if (with->IsBot()) @@ -16767,6 +16558,11 @@ struct RecordKillCheck { void Client::RecordKilledNPCEvent(NPC *n) { + if (!n) { + LogError("NPC passed was invalid."); + return; + } + bool is_named = Strings::Contains(n->GetName(), "#") && !n->IsRaidTarget(); std::vector checks = { @@ -17170,11 +16966,15 @@ void Client::Handle_OP_GuildTributeDonateItem(const EQApplicationPacket *app) SendGuildTributeDonateItemReply(in, favor); if(player_event_logs.IsEventEnabled(PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM)) { - auto e = PlayerEvent::GuildTributeDonateItem { - .item_id = inst->GetID(), - .guild_favor = favor + auto e = PlayerEvent::GuildTributeDonateItem{ .item_id = inst->GetID(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .guild_favor = favor }; - RecordPlayerEventLog(PlayerEvent::GUILD_TRIBUTE_DONATE_ITEM, e); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 8fe3b5ff9..172d8ca2a 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -703,12 +703,6 @@ void Client::OnDisconnect(bool hard_disconnect) { if (r) { r->MemberZoned(this); } - - /* QS: PlayerLogConnectDisconnect */ - if (RuleB(QueryServ, PlayerLogConnectDisconnect)) { - std::string event_desc = StringFormat("Disconnect :: in zoneid:%i instid:%i", GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Connect_State, CharacterID(), event_desc); - } } if (!bZoning) { diff --git a/zone/command.cpp b/zone/command.cpp index 94a0ef929..f99a6b5a3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -495,17 +495,6 @@ int command_realdispatch(Client *c, std::string message, bool ignore_status) } } - /* QS: Player_Log_Issued_Commands */ - if (RuleB(QueryServ, PlayerLogIssuedCommandes)) { - auto event_desc = fmt::format( - "Issued command :: '{}' in Zone ID: {} Instance ID: {}", - message, - c->GetZoneID(), - c->GetInstanceID() - ); - QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); - } - if (current_command->admin >= COMMANDS_LOGGING_MIN_STATUS) { LogCommands( "[{}] ([{}]) used command: [{}] (target=[{}])", diff --git a/zone/corpse.cpp b/zone/corpse.cpp index ce77061b1..387813b32 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -31,12 +31,14 @@ #include "../common/repositories/character_corpses_repository.h" #include "../common/repositories/character_corpse_items_repository.h" #include +#include "queryserv.h" extern EntityList entity_list; -extern Zone *zone; +extern Zone *zone; extern WorldServer worldserver; extern npcDecayTimes_Struct npcCorpseDecayTimes[100]; +extern QueryServ *QServ; void Corpse::SendEndLootErrorPacket(Client *client) { @@ -1569,11 +1571,17 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) if (player_event_logs.IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { auto e = PlayerEvent::LootItemEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .npc_id = GetNPCTypeID(), - .corpse_name = EntityList::RemoveNumbers(corpse_name) + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .npc_id = GetNPCTypeID(), + .corpse_name = EntityList::RemoveNumbers(corpse_name) }; RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 931f43338..95246fd9d 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2430,11 +2430,6 @@ void Perl__qs_send_query(std::string query) QServ->SendQuery(std::move(query)); } -void Perl__qs_player_event(int char_id, std::string message) -{ - QServ->PlayerLogEvent(Player_Log_Quest, char_id, message); -} - void Perl__log(int category, const char* message) { if (category < Logs::None || category >= Logs::MaxCategoryID) @@ -6768,7 +6763,6 @@ void perl_register_quest() package.add("popuptablerow", &Perl__popuptablerow); package.add("processmobswhilezoneempty", &Perl__processmobswhilezoneempty); package.add("pvp", &Perl__pvp); - package.add("qs_player_event", &Perl__qs_player_event); package.add("qs_send_query", &Perl__qs_send_query); package.add("rain", &Perl__rain); package.add("rebind", (void(*)(int, float, float, float))&Perl__rebind); diff --git a/zone/exp.cpp b/zone/exp.cpp index a7ebee711..bd2bacb74 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -931,17 +931,6 @@ void Client::SetLevel(uint8 set_level, bool command) RecordPlayerEventLog(PlayerEvent::LEVEL_GAIN, e); } - - if (RuleB(QueryServ, PlayerLogLevels)) { - const auto event_desc = fmt::format( - "Leveled UP :: to Level:{} from Level:{} in zoneid:{} instid:{}", - set_level, - m_pp.level, - GetZoneID(), - GetInstanceID() - ); - QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); - } } else if (set_level < m_pp.level) { int levels_lost = (m_pp.level - set_level); @@ -958,17 +947,6 @@ void Client::SetLevel(uint8 set_level, bool command) RecordPlayerEventLog(PlayerEvent::LEVEL_LOSS, e); } - - if (RuleB(QueryServ, PlayerLogLevels)) { - const auto event_desc = fmt::format( - "Leveled DOWN :: to Level:{} from Level:{} in zoneid:{} instid:{}", - set_level, - m_pp.level, - GetZoneID(), - GetInstanceID() - ); - QServ->PlayerLogEvent(Player_Log_Levels, CharacterID(), event_desc); - } } m_pp.level = set_level; diff --git a/zone/forage.cpp b/zone/forage.cpp index 1037c1fbb..a6ad1b648 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -35,8 +35,10 @@ #include "../common/repositories/fishing_repository.h" #include "../common/events/player_event_logs.h" #include "worldserver.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; #ifdef _WINDOWS #define snprintf _snprintf @@ -379,15 +381,20 @@ void Client::GoFish(bool guarantee, bool use_bait) if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::FISH_SUCCESS)) { auto e = PlayerEvent::FishSuccessEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, }; - RecordPlayerEventLog(PlayerEvent::FISH_SUCCESS, e); } if (parse->PlayerHasQuestSub(EVENT_FISH_SUCCESS)) { - std::vector args = { inst }; + std::vector args = {inst}; parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); } } @@ -512,8 +519,14 @@ void Client::ForageItem(bool guarantee) { if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::FORAGE_SUCCESS)) { auto e = PlayerEvent::ForageSuccessEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name + .item_id = inst->GetItem()->ID, + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, }; RecordPlayerEventLog(PlayerEvent::FORAGE_SUCCESS, e); } diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 6e1f66d1c..897f3275b 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -1,7 +1,9 @@ #include "../client.h" #include "../worldserver.h" +#include "../queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; #include "../guild_mgr.h" #include "../doors.h" @@ -600,7 +602,36 @@ void command_guild(Client* c, const Seperator* sep) else { auto guild_id = Strings::ToUnsignedInt(sep->arg[2]); auto guild = guild_mgr.GetGuildByGuildID(guild_id); - c->SendGuildMembersList(); + + PlayerEvent::LootItemEvent e{}; + e.charges = -1; + e.corpse_name = "Test Corpse Name"; + e.item_id = 123456789; + e.item_name = "Test Item Name"; + e.npc_id = 987654321; + e.augment_1_id = 11; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 44; + e.augment_5_id = 55; + e.augment_6_id = 66; + + RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); + + PlayerEvent::DestroyItemEvent e2{}; + e2.charges = -1; + e2.attuned = true; + e.augment_1_id = 11; + e.augment_2_id = 0; + e.augment_3_id = 0; + e.augment_4_id = 44; + e.augment_5_id = 55; + e.augment_6_id = 66; + e2.item_id = 123456789; + e2.item_name = "Test Item Destroy Name"; + e2.reason = "Test Item Destroy Reason"; + + RecordPlayerEventLogWithClient(c, PlayerEvent::ITEM_DESTROY, e2); } } } diff --git a/zone/gm_commands/parcels.cpp b/zone/gm_commands/parcels.cpp index 740d078e7..710f1b4a9 100644 --- a/zone/gm_commands/parcels.cpp +++ b/zone/gm_commands/parcels.cpp @@ -202,6 +202,12 @@ void command_parcels(Client *c, const Seperator *sep) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = parcel_out.item_id; + e.augment_1_id = inst->GetAugmentItemID(0); + e.augment_2_id = inst->GetAugmentItemID(1); + e.augment_3_id = inst->GetAugmentItemID(2); + e.augment_4_id = inst->GetAugmentItemID(3); + e.augment_5_id = inst->GetAugmentItemID(4); + e.augment_6_id = inst->GetAugmentItemID(5); e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; @@ -280,6 +286,12 @@ void command_parcels(Client *c, const Seperator *sep) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = parcel_out.item_id; + e.augment_1_id = inst->GetAugmentItemID(0); + e.augment_2_id = inst->GetAugmentItemID(1); + e.augment_3_id = inst->GetAugmentItemID(2); + e.augment_4_id = inst->GetAugmentItemID(3); + e.augment_5_id = inst->GetAugmentItemID(4); + e.augment_6_id = inst->GetAugmentItemID(5); e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; diff --git a/zone/groups.cpp b/zone/groups.cpp index 6e5d2c489..846c1dde9 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -25,10 +25,12 @@ #include "../common/events/player_event_logs.h" #include "../common/repositories/group_id_repository.h" #include "../common/repositories/group_leaders_repository.h" +#include "queryserv.h" -extern EntityList entity_list; +extern EntityList entity_list; extern WorldServer worldserver; +extern QueryServ *QServ; /* note about how groups work: diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 129cda55e..a6e21c9e3 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -27,8 +27,10 @@ #include "bot.h" #include "../common/evolving_items.h" #include "../common/repositories/character_corpse_items_repository.h" +#include "queryserv.h" extern WorldServer worldserver; +extern QueryServ *QServ; // @merth: this needs to be touched up uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { @@ -631,17 +633,17 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_CREATION)) { auto e = PlayerEvent::ItemCreationEvent{}; - e.item_id = item->ID; - e.item_name = item->Name; - e.to_slot = to_slot; - e.charges = charges; - e.aug1 = aug1; - e.aug2 = aug2; - e.aug3 = aug3; - e.aug4 = aug4; - e.aug5 = aug5; - e.aug6 = aug6; - e.attuned = attuned; + e.item_id = item->ID; + e.item_name = item->Name; + e.to_slot = to_slot; + e.charges = charges; + e.augment_1_id = aug1; + e.augment_2_id = aug2; + e.augment_3_id = aug3; + e.augment_4_id = aug4; + e.augment_5_id = aug5; + e.augment_6_id = aug6; + e.attuned = attuned; RecordPlayerEventLog(PlayerEvent::ITEM_CREATION, e); } @@ -763,10 +765,16 @@ void Client::DropItem(int16 slot_id, bool recurse) if (player_event_logs.IsEventEnabled(PlayerEvent::DROPPED_ITEM)) { auto e = PlayerEvent::DroppedItemEvent{ - .item_id = inst->GetID(), - .item_name = inst->GetItem()->Name, - .slot_id = slot_id, - .charges = (uint32) inst->GetCharges() + .item_id = inst->GetID(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .item_name = inst->GetItem()->Name, + .slot_id = slot_id, + .charges = (uint32) inst->GetCharges() }; RecordPlayerEventLog(PlayerEvent::DROPPED_ITEM, e); } @@ -820,79 +828,10 @@ void Client::DropItem(int16 slot_id, bool recurse) object->StartDecay(); LogInventory("[{}] dropped [{}] from slot [{}]", GetCleanName(), inst->GetItem()->Name, slot_id); - DropItemQS(inst, false); safe_delete(inst); } -void Client::DropItemQS(EQ::ItemInstance* inst, bool pickup) { - if (RuleB(QueryServ, PlayerDropItems)) { - QSPlayerDropItem_Struct qs_audit; - std::list event_details; - memset(&qs_audit, 0, sizeof(QSPlayerDropItem_Struct)); - - qs_audit.char_id = character_id; - qs_audit.pickup = pickup; - qs_audit.zone_id = GetZoneID(); - qs_audit.x = (int) GetX(); - qs_audit.y = (int) GetY(); - qs_audit.z = (int) GetZ(); - - if (inst) { - auto detail = new QSDropItems_Struct; - detail->item_id = inst->GetID(); - detail->charges = inst->IsClassBag() ? 1 : inst->GetCharges(); - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - event_details.push_back(detail); - - if (inst->IsClassBag()) { - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items - const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); - if (bag_inst) { - detail = new QSDropItems_Struct; - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - event_details.push_back(detail); - } - } - } - } - qs_audit._detail_count = event_details.size(); - - auto qs_pack = new ServerPacket( - ServerOP_QSPlayerDropItem, - sizeof(QSPlayerDropItem_Struct) + - (sizeof(QSDropItems_Struct) * qs_audit._detail_count)); - QSPlayerDropItem_Struct* qs_buf = (QSPlayerDropItem_Struct*) qs_pack->pBuffer; - - memcpy(qs_buf, &qs_audit, sizeof(QSPlayerDropItem_Struct)); - - int offset = 0; - - for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSDropItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - } -} - // Drop inst void Client::DropInst(const EQ::ItemInstance* inst) { @@ -1041,55 +980,6 @@ void Client::DeleteItemInInventory(int16 slot_id, int16 quantity, bool client_up return; } - // start QS code - if(RuleB(QueryServ, PlayerLogDeletes)) { - uint16 delete_count = 0; - - if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); } - - auto qspack = - new ServerPacket(ServerOP_QSPlayerLogDeletes, - sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); - QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer; - uint16 parent_offset = 0; - - qsaudit->char_id = character_id; - qsaudit->stack_size = quantity; - qsaudit->char_count = delete_count; - - qsaudit->items[parent_offset].char_slot = slot_id; - qsaudit->items[parent_offset].item_id = m_inv[slot_id]->GetID(); - qsaudit->items[parent_offset].charges = m_inv[slot_id]->GetCharges(); - qsaudit->items[parent_offset].aug_1 = m_inv[slot_id]->GetAugmentItemID(1); - qsaudit->items[parent_offset].aug_2 = m_inv[slot_id]->GetAugmentItemID(2); - qsaudit->items[parent_offset].aug_3 = m_inv[slot_id]->GetAugmentItemID(3); - qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4); - qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); - - if (m_inv[slot_id]->IsClassBag()) { - for (uint8 bag_idx = EQ::invbag::SLOT_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { - EQ::ItemInstance* bagitem = m_inv[slot_id]->GetItem(bag_idx); - - if(bagitem) { - int16 bagslot_id = EQ::InventoryProfile::CalcSlotId(slot_id, bag_idx); - - qsaudit->items[++parent_offset].char_slot = bagslot_id; - qsaudit->items[parent_offset].item_id = bagitem->GetID(); - qsaudit->items[parent_offset].charges = bagitem->GetCharges(); - qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1); - qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2); - qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3); - qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4); - qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5); - } - } - } - - if(worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - uint64 evolve_id = m_inv[slot_id]->GetEvolveUniqueID(); bool isDeleted = m_inv.DeleteItem(slot_id, quantity); if (isDeleted && evolve_id && (slot_id > EQ::invslot::TRADE_END || slot_id < EQ::invslot::TRADE_BEGIN)) { @@ -1732,7 +1622,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit if (ClientVersion() >= EQ::versions::ClientVersion::RoF) { return true; } // Can't do RoF+ if (move_in->to_slot == EQ::invslot::slotCursor) { @@ -1768,10 +1657,17 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { auto e = PlayerEvent::DestroyItemEvent{ - .item_id = test_inst->GetItem()->ID, - .item_name = test_inst->GetItem()->Name, - .charges = test_inst->GetCharges(), - .reason = "Duplicate lore item", + .item_id = test_inst->GetItem()->ID, + .item_name = test_inst->GetItem()->Name, + .charges = test_inst->GetCharges(), + .augment_1_id = test_inst->GetAugmentItemID(0), + .augment_2_id = test_inst->GetAugmentItemID(1), + .augment_3_id = test_inst->GetAugmentItemID(2), + .augment_4_id = test_inst->GetAugmentItemID(3), + .augment_5_id = test_inst->GetAugmentItemID(4), + .augment_6_id = test_inst->GetAugmentItemID(5), + .attuned = test_inst->IsAttuned(), + .reason = "Duplicate lore item" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -1785,17 +1681,23 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (move_in->to_slot == (uint32)INVALID_INDEX) { if (move_in->from_slot == (uint32)EQ::invslot::slotCursor) { LogInventory("Client destroyed item from cursor slot [{}]", move_in->from_slot); - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit EQ::ItemInstance *inst = m_inv.GetItem(EQ::invslot::slotCursor); if (inst) { if (player_event_logs.IsEventEnabled(PlayerEvent::ITEM_DESTROY)) { auto e = PlayerEvent::DestroyItemEvent{ - .item_id = inst->GetItem()->ID, - .item_name = inst->GetItem()->Name, - .charges = inst->GetCharges(), - .reason = "Client destroy cursor", + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = inst->GetCharges(), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .attuned = inst->IsAttuned(), + .reason = "Client destroy cursor" }; RecordPlayerEventLog(PlayerEvent::ITEM_DESTROY, e); @@ -1818,7 +1720,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { LogInventory("Deleted item from slot [{}] as a result of an inventory container tradeskill combine", move_in->from_slot); - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit DeleteItemInInventory(move_in->from_slot); return true; // Item deletion } @@ -2015,8 +1916,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { safe_delete(inst); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit - return true; } else if (dst_slot_id >= EQ::invslot::WORLD_BEGIN && dst_slot_id <= EQ::invslot::WORLD_END) { @@ -2085,8 +1984,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv[src_slot_id], src_slot_id); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit - return true; } } @@ -2105,10 +2002,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return false; } - // Add cursor item to trade bucket - // Also sends trade information to other client of trade session - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - trade->AddEntity(dst_slot_id, move_in->number_in_stack); if (dstitemid == 0) { @@ -2117,8 +2010,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } else { - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - SummonItem(src_inst->GetID(), src_inst->GetCharges()); DeleteItemInInventory(EQ::invslot::slotCursor); @@ -2339,8 +2230,6 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv.GetItem(dst_slot_id), dst_slot_id); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit - // Step 8: Re-calc stats CalcBonuses(); ApplyWeaponsStance(); @@ -2442,104 +2331,6 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { } } -void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { - int16 from_slot_id = static_cast(move_in->from_slot); - int16 to_slot_id = static_cast(move_in->to_slot); - int16 move_amount = static_cast(move_in->number_in_stack); - - if(!m_inv[from_slot_id] && !m_inv[to_slot_id]) { return; } - - uint16 move_count = 0; - - if(m_inv[from_slot_id]) { move_count += m_inv[from_slot_id]->GetTotalItemCount(); } - if(to_slot_id != from_slot_id) { if(m_inv[to_slot_id]) { move_count += m_inv[to_slot_id]->GetTotalItemCount(); } } - - auto qspack = new ServerPacket(ServerOP_QSPlayerLogMoves, - sizeof(QSPlayerLogMove_Struct) + (sizeof(QSMoveItems_Struct) * move_count)); - QSPlayerLogMove_Struct* qsaudit = (QSPlayerLogMove_Struct*)qspack->pBuffer; - - qsaudit->char_id = character_id; - qsaudit->stack_size = move_amount; - qsaudit->char_count = move_count; - qsaudit->postaction = postaction_call; - qsaudit->from_slot = from_slot_id; - qsaudit->to_slot = to_slot_id; - - move_count = 0; - - const EQ::ItemInstance* from_inst = m_inv[postaction_call?to_slot_id:from_slot_id]; - - if(from_inst) { - qsaudit->items[move_count].from_slot = from_slot_id; - qsaudit->items[move_count].to_slot = to_slot_id; - qsaudit->items[move_count].item_id = from_inst->GetID(); - qsaudit->items[move_count].charges = from_inst->GetCharges(); - qsaudit->items[move_count].aug_1 = from_inst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = from_inst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = from_inst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = from_inst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = from_inst->GetAugmentItemID(5); - - if (from_inst->IsType(EQ::item::ItemClassBag)) { - for (uint8 bag_idx = EQ::invbag::SLOT_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { - const EQ::ItemInstance* from_baginst = from_inst->GetItem(bag_idx); - - if(from_baginst) { - qsaudit->items[move_count].from_slot = EQ::InventoryProfile::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = EQ::InventoryProfile::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].item_id = from_baginst->GetID(); - qsaudit->items[move_count].charges = from_baginst->GetCharges(); - qsaudit->items[move_count].aug_1 = from_baginst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = from_baginst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = from_baginst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = from_baginst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = from_baginst->GetAugmentItemID(5); - } - } - } - } - - if(to_slot_id != from_slot_id) { - const EQ::ItemInstance* to_inst = m_inv[postaction_call?from_slot_id:to_slot_id]; - - if(to_inst) { - qsaudit->items[move_count].from_slot = to_slot_id; - qsaudit->items[move_count].to_slot = from_slot_id; - qsaudit->items[move_count].item_id = to_inst->GetID(); - qsaudit->items[move_count].charges = to_inst->GetCharges(); - qsaudit->items[move_count].aug_1 = to_inst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = to_inst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = to_inst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = to_inst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = to_inst->GetAugmentItemID(5); - - if (to_inst->IsType(EQ::item::ItemClassBag)) { - for (uint8 bag_idx = EQ::invbag::SLOT_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { - const EQ::ItemInstance* to_baginst = to_inst->GetItem(bag_idx); - - if(to_baginst) { - qsaudit->items[move_count].from_slot = EQ::InventoryProfile::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = EQ::InventoryProfile::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].item_id = to_baginst->GetID(); - qsaudit->items[move_count].charges = to_baginst->GetCharges(); - qsaudit->items[move_count].aug_1 = to_baginst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = to_baginst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = to_baginst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = to_baginst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = to_baginst->GetAugmentItemID(5); - } - } - } - } - } - - if(move_count && worldserver.Connected()) { - worldserver.SendPacket(qspack); - } - - safe_delete(qspack); -} - void Client::DyeArmor(EQ::TintProfile* dye){ int16 slot=0; for (int i = EQ::textures::textureBegin; i <= EQ::textures::LastTintableTexture; i++) { diff --git a/zone/main.cpp b/zone/main.cpp index 007f9f22a..63e1eb80c 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -483,6 +483,8 @@ int main(int argc, char **argv) LogInfo("Loading quests"); parse->ReloadQuests(); + QServ->CheckForConnectState(); + worldserver.Connect(); worldserver.SetScheduler(&event_scheduler); @@ -631,10 +633,11 @@ int main(int argc, char **argv) if (quest_timers.Check()) { quest_manager.Process(); } - } } + QServ->CheckForConnectState(); + if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); @@ -672,6 +675,7 @@ int main(int argc, char **argv) LogSys.CloseFileLogs(); safe_delete(mutex); + safe_delete(QServ); return 0; } diff --git a/zone/npc.cpp b/zone/npc.cpp index 35f9c201c..31664a8ec 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -65,6 +65,7 @@ #endif extern Zone* zone; +extern QueryServ* QServ; extern volatile bool is_zone_loaded; extern EntityList entity_list; diff --git a/zone/object.cpp b/zone/object.cpp index f740bf93c..af4993dbe 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -31,15 +31,17 @@ #include "../common/events/player_event_logs.h" #include "../common/repositories/ground_spawns_repository.h" #include "../common/repositories/object_repository.h" +#include "queryserv.h" const char DEFAULT_OBJECT_NAME[] = "IT63_ACTORDEF"; const char DEFAULT_OBJECT_NAME_SUFFIX[] = "_ACTORDEF"; -extern Zone* zone; -extern EntityList entity_list; +extern Zone *zone; +extern EntityList entity_list; extern WorldServer worldserver; +extern QueryServ *QServ; // Loading object from database Object::Object( @@ -661,8 +663,6 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) sender->DeleteItemInInventory(EQ::invslot::slotCursor, 1, true); } - sender->DropItemQS(m_inst, true); - if (!m_ground_spawn) { safe_delete(m_inst); } diff --git a/zone/parcels.cpp b/zone/parcels.cpp index e3661906f..925deb7e0 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -27,6 +27,7 @@ #include "../common/ruletypes.h" extern WorldServer worldserver; +extern QueryServ *QServ; void Client::SendBulkParcels() { @@ -461,12 +462,12 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = parcel_out.item_id; - e.aug_slot_1 = parcel_out.aug_slot_1; - e.aug_slot_2 = parcel_out.aug_slot_2; - e.aug_slot_3 = parcel_out.aug_slot_3; - e.aug_slot_4 = parcel_out.aug_slot_4; - e.aug_slot_5 = parcel_out.aug_slot_5; - e.aug_slot_6 = parcel_out.aug_slot_6; + e.augment_1_id = parcel_out.aug_slot_1; + e.augment_2_id = parcel_out.aug_slot_2; + e.augment_3_id = parcel_out.aug_slot_3; + e.augment_4_id = parcel_out.aug_slot_4; + e.augment_5_id = parcel_out.aug_slot_5; + e.augment_6_id = parcel_out.aug_slot_6; e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; @@ -477,12 +478,12 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) e.from_player_name = parcel_out.from_name; e.to_player_name = send_to_client.at(0).character_name; e.item_id = i.item_id; - e.aug_slot_1 = i.aug_slot_1; - e.aug_slot_2 = i.aug_slot_2; - e.aug_slot_3 = i.aug_slot_3; - e.aug_slot_4 = i.aug_slot_4; - e.aug_slot_5 = i.aug_slot_5; - e.aug_slot_6 = i.aug_slot_6; + e.augment_1_id = i.aug_slot_1; + e.augment_2_id = i.aug_slot_2; + e.augment_3_id = i.aug_slot_3; + e.augment_4_id = i.aug_slot_4; + e.augment_5_id = i.aug_slot_5; + e.augment_6_id = i.aug_slot_6; e.quantity = i.quantity; e.sent_date = parcel_out.sent_date; RecordPlayerEventLog(PlayerEvent::PARCEL_SEND, e); @@ -775,12 +776,12 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in) PlayerEvent::ParcelRetrieve e{}; e.from_player_name = p->second.from_name; e.item_id = p->second.item_id; - e.aug_slot_1 = p->second.aug_slot_1; - e.aug_slot_2 = p->second.aug_slot_2; - e.aug_slot_3 = p->second.aug_slot_3; - e.aug_slot_4 = p->second.aug_slot_4; - e.aug_slot_5 = p->second.aug_slot_5; - e.aug_slot_6 = p->second.aug_slot_6; + e.augment_1_id = p->second.aug_slot_1; + e.augment_2_id = p->second.aug_slot_2; + e.augment_3_id = p->second.aug_slot_3; + e.augment_4_id = p->second.aug_slot_4; + e.augment_5_id = p->second.aug_slot_5; + e.augment_6_id = p->second.aug_slot_6; e.quantity = p->second.quantity; e.sent_date = p->second.sent_date; RecordPlayerEventLog(PlayerEvent::PARCEL_RETRIEVE, e); @@ -788,12 +789,12 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in) for (auto const &i:results) { e.from_player_name = p->second.from_name; e.item_id = i.item_id; - e.aug_slot_1 = i.aug_slot_1; - e.aug_slot_2 = i.aug_slot_2; - e.aug_slot_3 = i.aug_slot_3; - e.aug_slot_4 = i.aug_slot_4; - e.aug_slot_5 = i.aug_slot_5; - e.aug_slot_6 = i.aug_slot_6; + e.augment_1_id = i.aug_slot_1; + e.augment_2_id = i.aug_slot_2; + e.augment_3_id = i.aug_slot_3; + e.augment_4_id = i.aug_slot_4; + e.augment_5_id = i.aug_slot_5; + e.augment_6_id = i.aug_slot_6; e.quantity = i.quantity; e.sent_date = p->second.sent_date; RecordPlayerEventLog(PlayerEvent::PARCEL_RETRIEVE, e); diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index de26c6be1..58bcae04a 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -1,21 +1,3 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - #include "../common/global_define.h" #include "../common/servertalk.h" #include "../common/strings.h" @@ -24,7 +6,7 @@ Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) extern WorldServer worldserver; -extern QueryServ *QServ; +extern QueryServ *QServ; QueryServ::QueryServ() { @@ -43,12 +25,50 @@ void QueryServ::SendQuery(std::string Query) safe_delete(pack); } -void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc) +void QueryServ::Connect() { - std::string query = StringFormat( - "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", - Event_Type, - Character_ID, - Strings::Escape(Event_Desc).c_str()); - SendQuery(query); + m_connection = std::make_unique(Config->QSHost, Config->QSPort, false, "Zone", Config->SharedKey); + m_connection->OnMessage(std::bind(&QueryServ::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); + m_connection->OnConnect([this](EQ::Net::ServertalkClient *client) { + m_is_qs_connected = true; + LogInfo("Query Server connection established to [{}] [{}]", client->Handle()->RemoteIP(), client->Handle()->RemotePort()); + }); + + LogInfo( + "New Query Server connection to [{}:{}]", + Config->QSHost, + Config->QSPort + ); +} + +bool QueryServ::SendPacket(ServerPacket *pack) +{ + if (m_connection.get() == nullptr) { + Connect(); + } + + if (!m_connection.get()) { + return false; + } + + if (m_is_qs_connected) { + m_connection->SendPacket(pack); + return true; + } + + LogInfo("SendPacket request with QS Server Offline."); + return false; +} + +void QueryServ::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) +{ + ServerPacket tpack(opcode, p); + auto pack = &tpack; + + switch (opcode) { + default: { + LogInfo("Unknown ServerOP Received [{}]", opcode); + break; + } + } } diff --git a/zone/queryserv.h b/zone/queryserv.h index 69392037c..f1a100c31 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -1,37 +1,62 @@ #ifndef QUERYSERV_ZONE_H #define QUERYSERV_ZONE_H +#include "../common/net/servertalk_server.h" +#include "../common/net/servertalk_client_connection.h" +#include "../common/event/timer.h" +#include "../common/rulesys.h" +#include "../common/eqemu_logsys.h" -/* - enum PlayerGenericLogEventTypes - These Enums are for the generic logging table that are not complex and require more advanced logic -*/ +class QueryServ { +public: + QueryServ(); + ~QueryServ(); + void SendQuery(std::string Query); + void Connect(); + inline void Disconnect() { + if (m_connection) { + m_connection->Handle()->Disconnect(); + m_connection.reset(); + } + } + bool SendPacket(ServerPacket *pack); + void HandleMessage(uint16 opcode, const EQ::Net::Packet &p); -enum PlayerGenericLogEventTypes { - Player_Log_Quest = 1, - Player_Log_Zoning, - Player_Log_Deaths, - Player_Log_Connect_State, - Player_Log_Levels, - Player_Log_Keyring_Addition, - Player_Log_QGlobal_Update, - Player_Log_Task_Updates, - Player_Log_AA_Purchases, - Player_Log_Trade_Skill_Events, - Player_Log_Issued_Commands, - Player_Log_Money_Transactions, - Player_Log_Alternate_Currency_Transactions, - Player_Log_Guild_Tribute_Item_Donation, - Player_Log_Guild_Tribute_Plat_Donation + bool HasConnection() const + { + return m_connection && m_connection->Handle() && m_connection->Handle()->IsConnected(); + } + + inline void CheckForConnectState() { + if (RuleB(Logging, PlayerEventsQSProcess)) { + if (!m_connection) { + Connect(); + LogInfo("Starting QueryServ connection"); + } + } else { + if (HasConnection()) { + Disconnect(); + LogInfo("Stopping QueryServ connection"); + } + } + } + +private: + std::unique_ptr m_connection; + bool m_is_qs_connected = false; }; - -class QueryServ{ - public: - QueryServ(); - ~QueryServ(); - void SendQuery(std::string Query); - void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc); +class QueryServConnection { +public: + QueryServConnection(); + void AddConnection(std::shared_ptr connection); + void RemoveConnection(std::shared_ptr connection); + void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p); + void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p); + bool SendPacket(ServerPacket *pack); +private: + std::map> m_streams; + std::unique_ptr m_keepalive; }; #endif /* QUERYSERV_ZONE_H */ diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 310347285..d74e85a10 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1768,12 +1768,6 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti } InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); - - /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ - std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); - } } /* Inserts global variable into quest_globals table */ @@ -1860,12 +1854,6 @@ void QuestManager::delglobal(const char *varname) { else qgCharid=-qgNpcid; // make char id negative npc id as a fudge - /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ - std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); - } - std::string query = StringFormat("DELETE FROM quest_globals " "WHERE name = '%s' " "&& (npcid=0 || npcid=%i) " diff --git a/zone/raids.cpp b/zone/raids.cpp index 7bb6ab4e5..dd127684b 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -33,9 +33,11 @@ #include "bot.h" #include "worldserver.h" +#include "queryserv.h" -extern EntityList entity_list; +extern EntityList entity_list; extern WorldServer worldserver; +extern QueryServ *QServ; Raid::Raid(uint32 raidID) : GroupIDConsumer(raidID) diff --git a/zone/spells.cpp b/zone/spells.cpp index feaf38bcd..f604d7b3b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -89,6 +89,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include #include +#include "queryserv.h" #ifndef WIN32 #include @@ -106,10 +107,11 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "mob.h" #include "water_map.h" -extern Zone* zone; +extern Zone *zone; extern volatile bool is_zone_loaded; -extern WorldServer worldserver; -extern FastMath g_Math; +extern WorldServer worldserver; +extern FastMath g_Math; +extern QueryServ *QServ; using EQ::spells::CastingSlot; diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 2b7f89ea9..0dfa3d8a6 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -914,17 +914,6 @@ int ClientTaskState::IncrementDoneCount( parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, client, export_string, 0); } } - /* QS: PlayerLogTaskUpdates :: Update */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)) { - std::string event_desc = StringFormat( - "Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", - info->task_id, - info->activity[activity_id].activity_id, - info->activity[activity_id].done_count, - client->GetZoneID(), - client->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); - } // If this task is now complete, the Completed tasks will have been // updated in UnlockActivities. Send the completed task list to the @@ -947,18 +936,6 @@ int ClientTaskState::IncrementDoneCount( RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_COMPLETE, e); } - /* QS: PlayerLogTaskUpdates :: Complete */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)) { - std::string event_desc = StringFormat( - "Task Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", - info->task_id, - info->activity[activity_id].activity_id, - info->activity[activity_id].done_count, - client->GetZoneID(), - client->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); - } - client->SendTaskActivityComplete(info->task_id, 0, task_index, task_data->type, 0); // If Experience and/or cash rewards are set, reward them from the task even if reward_method is METHODQUEST diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 34cb4d6c4..3e6ec9992 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -198,9 +198,9 @@ bool TaskManager::LoadTasks(int single_task) ad->target_name = a.target_name; ad->item_list = a.item_list; ad->skill_list = a.skill_list; - ad->skill_id = Strings::IsNumber(a.skill_list) ? Strings::ToInt(a.skill_list) : 0; // for older clients + ad->skill_id = !a.skill_list.empty() && Strings::IsNumber(a.skill_list) ? Strings::ToInt(a.skill_list) : 0; // for older clients ad->spell_list = a.spell_list; - ad->spell_id = Strings::IsNumber(a.spell_list) ? Strings::ToInt(a.spell_list) : 0; // for older clients + ad->spell_id = !a.skill_list.empty() && Strings::IsNumber(a.spell_list) ? Strings::ToInt(a.spell_list) : 0; // for older clients ad->description_override = a.description_override; ad->npc_match_list = a.npc_match_list; ad->item_id_list = a.item_id_list; diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index d0abc1b5f..1181a5f9d 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1172,13 +1172,6 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { ); } - /* QS: Player_Log_Trade_Skill_Events */ - if (RuleB(QueryServ, PlayerLogTradeSkillEvents)) { - - std::string event_desc = StringFormat("Success :: fashioned recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, CharacterID(), event_desc); - } - if (RuleB(TaskSystem, EnableTaskSystem)) { UpdateTasksForItem(TaskActivityType::TradeSkill, itr->first, itr->second); } @@ -1203,12 +1196,6 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { } - /* QS: Player_Log_Trade_Skill_Events */ - if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){ - std::string event_desc = StringFormat("Failed :: recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, CharacterID(), event_desc); - } - itr = spec->onfail.begin(); while(itr != spec->onfail.end()) { //should we check these arguments? diff --git a/zone/trading.cpp b/zone/trading.cpp index c2c04645b..fc3fe1ba0 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -326,38 +326,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (tradingWith->IsClient()) { Client * other = tradingWith->CastToClient(); - PlayerLogTrade_Struct * qs_audit = nullptr; - bool qs_log = false; if(other) { LogTrading("Finishing trade with client [{}]", other->GetName()); AddMoneyToPP(other->trade->cp, other->trade->sp, other->trade->gp, other->trade->pp, true); - // step 0: pre-processing - // QS code - if (RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - qs_audit = (PlayerLogTrade_Struct*)event_entry; - qs_log = true; - - if (finalizer) { - qs_audit->character_2_id = character_id; - - qs_audit->character_2_money.platinum = trade->pp; - qs_audit->character_2_money.gold = trade->gp; - qs_audit->character_2_money.silver = trade->sp; - qs_audit->character_2_money.copper = trade->cp; - } - else { - qs_audit->character_1_id = character_id; - - qs_audit->character_1_money.platinum = trade->pp; - qs_audit->character_1_money.gold = trade->gp; - qs_audit->character_1_money.silver = trade->sp; - qs_audit->character_1_money.copper = trade->cp; - } - } - // step 1: process bags for (int16 trade_slot = EQ::invslot::TRADE_BEGIN; trade_slot <= EQ::invslot::TRADE_END; ++trade_slot) { const EQ::ItemInstance* inst = m_inv[trade_slot]; @@ -377,55 +351,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(free_slot, *inst, true)) { inst->TransferOwnership(database, other->CharacterID()); LogTrading("Container [{}] ([{}]) successfully transferred, deleting from trade slot", inst->GetItem()->Name, inst->GetItem()->ID); - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = inst->GetID(); - detail->charges = 1; - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items - const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); - - if (bag_inst) { - detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = EQ::InventoryProfile::CalcSlotId(trade_slot, sub_slot); - detail->to_character_id = other->CharacterID(); - detail->to_slot = EQ::InventoryProfile::CalcSlotId(free_slot, sub_slot); - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - } - } - } } else { LogTrading("Transfer of container [{}] ([{}]) to [{}] failed, returning to giver", inst->GetItem()->Name, inst->GetItem()->ID, other->GetName()); @@ -492,28 +417,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st (old_charges - inst->GetCharges()) ); inst->TransferOwnership(database, other->CharacterID()); - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = partial_slot; - detail->item_id = inst->GetID(); - detail->charges = (old_charges - inst->GetCharges()); - detail->aug_1 = 0; - detail->aug_2 = 0; - detail->aug_3 = 0; - detail->aug_4 = 0; - detail->aug_5 = 0; - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - } } else { LogTrading("Transfer of partial stack [{}] ([{}]) to [{}] failed, returning [{}] charges to trade slot", @@ -560,24 +463,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st inst->SetCharges(0); } - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = character_id; - detail->to_slot = bias_slot; - detail->item_id = inst->GetID(); - detail->charges = (old_charges - inst->GetCharges()); - detail->aug_1 = 0; - detail->aug_2 = 0; - detail->aug_3 = 0; - detail->aug_4 = 0; - detail->aug_5 = 0; - - event_details->push_back(detail); - } - if (inst->GetCharges() == 0) { DeleteItemInInventory(trade_slot); break; @@ -601,56 +486,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(free_slot, *inst, true)) { inst->TransferOwnership(database, other->CharacterID()); LogTrading("Item [{}] ([{}]) successfully transferred, deleting from trade slot", inst->GetItem()->Name, inst->GetItem()->ID); - if (qs_log) { - auto detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = inst->GetID(); - detail->charges = (!inst->IsStackable() ? 1 : inst->GetCharges()); - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - - // 'step 3' should never really see containers..but, just in case... - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; (sub_slot <= EQ::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items - const EQ::ItemInstance* bag_inst = inst->GetItem(sub_slot); - - if (bag_inst) { - detail = new PlayerLogTradeItemsEntry_Struct; - - detail->from_character_id = character_id; - detail->from_slot = trade_slot; - detail->to_character_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->character_2_item_count += detail->charges; - else - qs_audit->character_1_item_count += detail->charges; - } - } - } } else { LogTrading("Transfer of Item [{}] ([{}]) to [{}] failed, returning to giver", inst->GetItem()->Name, inst->GetItem()->ID, other->GetName()); @@ -676,79 +511,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } else if(tradingWith->IsNPC()) { - QSPlayerLogHandin_Struct* qs_audit = nullptr; - bool qs_log = false; - - // QS code - if(RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - // Currently provides only basic functionality. Calling method will also - // need to be modified before item returns and rewards can be logged. - qs_audit = (QSPlayerLogHandin_Struct*)event_entry; - qs_log = true; - - qs_audit->quest_id = 0; - qs_audit->char_id = character_id; - qs_audit->char_money.platinum = trade->pp; - qs_audit->char_money.gold = trade->gp; - qs_audit->char_money.silver = trade->sp; - qs_audit->char_money.copper = trade->cp; - qs_audit->char_count = 0; - qs_audit->npc_id = tradingWith->GetNPCTypeID(); - qs_audit->npc_money.platinum = 0; - qs_audit->npc_money.gold = 0; - qs_audit->npc_money.silver = 0; - qs_audit->npc_money.copper = 0; - qs_audit->npc_count = 0; - } - - if(qs_log) { // This can be incorporated below when revisions are made - for (int16 trade_slot = EQ::invslot::TRADE_BEGIN; trade_slot <= EQ::invslot::TRADE_NPC_END; ++trade_slot) { - const EQ::ItemInstance* trade_inst = m_inv[trade_slot]; - - if(trade_inst) { - auto detail = new QSHandinItems_Struct; - - strcpy(detail->action_type, "HANDIN"); - - detail->char_slot = trade_slot; - detail->item_id = trade_inst->GetID(); - detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); - detail->aug_1 = trade_inst->GetAugmentItemID(1); - detail->aug_2 = trade_inst->GetAugmentItemID(2); - detail->aug_3 = trade_inst->GetAugmentItemID(3); - detail->aug_4 = trade_inst->GetAugmentItemID(4); - detail->aug_5 = trade_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - qs_audit->char_count += detail->charges; - - if (trade_inst->IsClassBag()) { - for (uint8 sub_slot = EQ::invbag::SLOT_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { - const EQ::ItemInstance* trade_baginst = trade_inst->GetItem(sub_slot); - - if(trade_baginst) { - detail = new QSHandinItems_Struct; - - strcpy(detail->action_type, "HANDIN"); - - detail->char_slot = EQ::InventoryProfile::CalcSlotId(trade_slot, sub_slot); - detail->item_id = trade_baginst->GetID(); - detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); - detail->aug_1 = trade_baginst->GetAugmentItemID(1); - detail->aug_2 = trade_baginst->GetAugmentItemID(2); - detail->aug_3 = trade_baginst->GetAugmentItemID(3); - detail->aug_4 = trade_baginst->GetAugmentItemID(4); - detail->aug_5 = trade_baginst->GetAugmentItemID(5); - - event_details->push_back(detail); - qs_audit->char_count += detail->charges; - } - } - } - } - } - } - bool quest_npc = false; if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) { quest_npc = true; @@ -1684,34 +1446,46 @@ void Client::BuyTraderItem(TraderBuy_Struct *tbs, Client *Trader, const EQApplic Trader->AddMoneyToPP(copper, silver, gold, platinum, true); if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) { - auto e = PlayerEvent::TraderPurchaseEvent{ - .item_id = buy_item->GetID(), - .item_name = buy_item->GetItem()->Name, - .trader_id = Trader->CharacterID(), - .trader_name = Trader->GetCleanName(), - .price = tbs->price, - .charges = outtbs->quantity, - .total_cost = (tbs->price * outtbs->quantity), - .player_money_balance = GetCarriedMoney(), - }; + auto e = PlayerEvent::TraderPurchaseEvent{ + .item_id = buy_item->GetID(), + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), + .item_name = buy_item->GetItem()->Name, + .trader_id = Trader->CharacterID(), + .trader_name = Trader->GetCleanName(), + .price = tbs->price, + .charges = outtbs->quantity, + .total_cost = (tbs->price * outtbs->quantity), + .player_money_balance = GetCarriedMoney(), + }; RecordPlayerEventLog(PlayerEvent::TRADER_PURCHASE, e); - } + } if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { - auto e = PlayerEvent::TraderSellEvent{ - .item_id = buy_item->GetID(), - .item_name = buy_item->GetItem()->Name, - .buyer_id = CharacterID(), - .buyer_name = GetCleanName(), - .price = tbs->price, - .charges = outtbs->quantity, - .total_cost = (tbs->price * outtbs->quantity), - .player_money_balance = Trader->GetCarriedMoney(), - }; + auto e = PlayerEvent::TraderSellEvent{ + .item_id = buy_item->GetID(), + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), + .item_name = buy_item->GetItem()->Name, + .buyer_id = CharacterID(), + .buyer_name = GetCleanName(), + .price = tbs->price, + .charges = outtbs->quantity, + .total_cost = (tbs->price * outtbs->quantity), + .player_money_balance = Trader->GetCarriedMoney(), + }; - RecordPlayerEventLogWithClient(Trader, PlayerEvent::TRADER_SELL, e); - } + RecordPlayerEventLogWithClient(Trader, PlayerEvent::TRADER_SELL, e); + } LogTrading("Trader Received: [{}] Platinum, [{}] Gold, [{}] Silver, [{}] Copper", platinum, gold, silver, copper); ReturnTraderReq(app, outtbs->quantity, item_id); @@ -3167,6 +2941,12 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_PURCHASE)) { auto e = PlayerEvent::TraderPurchaseEvent{ .item_id = buy_item->GetID(), + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), .item_name = buy_item->GetItem()->Name, .trader_id = tbs->trader_id, .trader_name = tbs->seller_name, @@ -3231,12 +3011,12 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati e.from_player_name = parcel_out.from_name; e.to_player_name = GetCleanName(); e.item_id = parcel_out.item_id; - e.aug_slot_1 = parcel_out.aug_slot_1; - e.aug_slot_2 = parcel_out.aug_slot_2; - e.aug_slot_3 = parcel_out.aug_slot_3; - e.aug_slot_4 = parcel_out.aug_slot_4; - e.aug_slot_5 = parcel_out.aug_slot_5; - e.aug_slot_6 = parcel_out.aug_slot_6; + e.augment_1_id = parcel_out.aug_slot_1; + e.augment_2_id = parcel_out.aug_slot_2; + e.augment_3_id = parcel_out.aug_slot_3; + e.augment_4_id = parcel_out.aug_slot_4; + e.augment_5_id = parcel_out.aug_slot_5; + e.augment_6_id = parcel_out.aug_slot_6; e.quantity = parcel_out.quantity; e.sent_date = parcel_out.sent_date; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 995887f17..accfd5a65 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -60,16 +60,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/repositories/guild_tributes_repository.h" #include "../common/patches/patches.h" #include "../common/skill_caps.h" +#include "queryserv.h" -extern EntityList entity_list; -extern Zone* zone; -extern volatile bool is_zone_loaded; -extern void Shutdown(); -extern WorldServer worldserver; -extern PetitionList petition_list; -extern uint32 numclients; -extern volatile bool RunLoops; +extern EntityList entity_list; +extern Zone *zone; +extern volatile bool is_zone_loaded; +extern void Shutdown(); +extern WorldServer worldserver; +extern PetitionList petition_list; +extern uint32 numclients; +extern volatile bool RunLoops; extern QuestParserCollection *parse; +extern QueryServ *QServ; // QuestParserCollection *parse = 0; @@ -4000,13 +4002,16 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) TraderRepository::UpdateActiveTransaction(database, in->id, false); - trader_pc->RemoveItemBySerialNumber(item_sn, in->trader_buy_struct.quantity); - trader_pc->AddMoneyToPP(in->trader_buy_struct.price * in->trader_buy_struct.quantity, true); - trader_pc->QueuePacket(outapp.get()); - if (player_event_logs.IsEventEnabled(PlayerEvent::TRADER_SELL)) { - auto e = PlayerEvent::TraderSellEvent{ + auto buy_item = trader_pc->FindTraderItemBySerialNumber(item_sn); + auto e = PlayerEvent::TraderSellEvent{ .item_id = in->trader_buy_struct.item_id, + .augment_1_id = buy_item->GetAugmentItemID(0), + .augment_2_id = buy_item->GetAugmentItemID(1), + .augment_3_id = buy_item->GetAugmentItemID(2), + .augment_4_id = buy_item->GetAugmentItemID(3), + .augment_5_id = buy_item->GetAugmentItemID(4), + .augment_6_id = buy_item->GetAugmentItemID(5), .item_name = in->trader_buy_struct.item_name, .buyer_id = in->buyer_id, .buyer_name = in->trader_buy_struct.buyer_name, @@ -4015,10 +4020,13 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) .total_cost = (in->trader_buy_struct.price * in->trader_buy_struct.quantity), .player_money_balance = trader_pc->GetCarriedMoney(), }; - RecordPlayerEventLogWithClient(trader_pc, PlayerEvent::TRADER_SELL, e); } + trader_pc->RemoveItemBySerialNumber(item_sn, in->trader_buy_struct.quantity); + trader_pc->AddMoneyToPP(in->trader_buy_struct.price * in->trader_buy_struct.quantity, true); + trader_pc->QueuePacket(outapp.get()); + break; } case ServerOP_BuyerMessaging: { diff --git a/zone/zoning.cpp b/zone/zoning.cpp index a02ab943a..d515ff168 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -489,12 +489,6 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc SendLogoutPackets(); - /* QS: PlayerLogZone */ - if (RuleB(QueryServ, PlayerLogZone)){ - std::string event_desc = StringFormat("Zoning :: zoneid:%u instid:%u x:%4.2f y:%4.2f z:%4.2f h:%4.2f zonemode:%d from zoneid:%u instid:%i", zone_id, instance_id, dest_x, dest_y, dest_z, dest_h, zone_mode, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Zoning, CharacterID(), event_desc); - } - /* Dont clear aggro until the zone is successful */ entity_list.RemoveFromHateLists(this);