diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 4efed4b6b..5aa76fac9 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -185,6 +185,7 @@ SET(repositories repositories/base/base_doors_repository.h repositories/base/base_dynamic_zones_repository.h repositories/base/base_dynamic_zone_members_repository.h + repositories/base/base_dynamic_zone_templates_repository.h repositories/base/base_eventlog_repository.h repositories/base/base_expeditions_repository.h repositories/base/base_expedition_lockouts_repository.h @@ -358,6 +359,7 @@ SET(repositories repositories/doors_repository.h repositories/dynamic_zones_repository.h repositories/dynamic_zone_members_repository.h + repositories/dynamic_zone_templates_repository.h repositories/eventlog_repository.h repositories/expeditions_repository.h repositories/expedition_lockouts_repository.h diff --git a/common/database_schema.h b/common/database_schema.h index 65379b2a1..94cc28e69 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -189,6 +189,7 @@ namespace DatabaseSchema { "char_create_point_allocations", "damageshieldtypes", "doors", + "dynamic_zone_templates", "faction_base_data", "faction_list", "faction_list_mod", diff --git a/common/dynamic_zone_base.cpp b/common/dynamic_zone_base.cpp index ee4ab82da..78b38de21 100644 --- a/common/dynamic_zone_base.cpp +++ b/common/dynamic_zone_base.cpp @@ -622,3 +622,28 @@ void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_ cereal::BinaryInputArchive archive(ss); archive(*this); } + +void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template) +{ + m_zone_id = dz_template.zone_id; + m_zone_version = dz_template.zone_version; + m_name = dz_template.name; + m_min_players = dz_template.min_players; + m_max_players = dz_template.max_players; + m_duration = std::chrono::seconds(dz_template.duration_seconds); + m_dz_switch_id = dz_template.dz_switch_id; + m_compass.zone_id = dz_template.compass_zone_id; + m_compass.x = dz_template.compass_x; + m_compass.y = dz_template.compass_y; + m_compass.z = dz_template.compass_z; + m_safereturn.zone_id = dz_template.return_zone_id; + m_safereturn.x = dz_template.return_x; + m_safereturn.y = dz_template.return_y; + m_safereturn.z = dz_template.return_z; + m_safereturn.heading = dz_template.return_h; + m_has_zonein = dz_template.override_zone_in; + m_zonein.x = dz_template.zone_in_x; + m_zonein.y = dz_template.zone_in_y; + m_zonein.z = dz_template.zone_in_z; + m_zonein.heading = dz_template.zone_in_h; +} diff --git a/common/dynamic_zone_base.h b/common/dynamic_zone_base.h index 0f06be8bf..b92f18ec2 100644 --- a/common/dynamic_zone_base.h +++ b/common/dynamic_zone_base.h @@ -5,6 +5,7 @@ #include "net/packet.h" #include "repositories/dynamic_zones_repository.h" #include "repositories/dynamic_zone_members_repository.h" +#include "repositories/dynamic_zone_templates_repository.h" #include #include #include @@ -74,6 +75,7 @@ public: virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0; + int GetDuration() const { return static_cast(m_duration.count()); } uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); } uint32_t GetID() const { return m_id; } uint16_t GetInstanceID() const { return static_cast(m_instance_id); } @@ -113,6 +115,7 @@ public: bool IsValid() const { return m_instance_id != 0; } bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; } void LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size); + void LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template); void RemoveAllMembers(); bool RemoveMember(uint32_t character_id); bool RemoveMember(const std::string& character_name); diff --git a/common/repositories/base/base_dynamic_zone_templates_repository.h b/common/repositories/base/base_dynamic_zone_templates_repository.h new file mode 100644 index 000000000..0e71e30a4 --- /dev/null +++ b/common/repositories/base/base_dynamic_zone_templates_repository.h @@ -0,0 +1,506 @@ +/** + * 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://eqemu.gitbook.io/server/in-development/developer-area/repositories + */ + +#ifndef EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H +#define EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H + +#include "../../database.h" +#include "../../strings.h" +#include + +class BaseDynamicZoneTemplatesRepository { +public: + struct DynamicZoneTemplates { + int id; + int zone_id; + int zone_version; + std::string name; + int min_players; + int max_players; + int duration_seconds; + int dz_switch_id; + int compass_zone_id; + float compass_x; + float compass_y; + float compass_z; + int return_zone_id; + float return_x; + float return_y; + float return_z; + float return_h; + int override_zone_in; + float zone_in_x; + float zone_in_y; + float zone_in_z; + float zone_in_h; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "zone_id", + "zone_version", + "name", + "min_players", + "max_players", + "duration_seconds", + "dz_switch_id", + "compass_zone_id", + "compass_x", + "compass_y", + "compass_z", + "return_zone_id", + "return_x", + "return_y", + "return_z", + "return_h", + "override_zone_in", + "zone_in_x", + "zone_in_y", + "zone_in_z", + "zone_in_h", + }; + } + + static std::vector SelectColumns() + { + return { + "id", + "zone_id", + "zone_version", + "name", + "min_players", + "max_players", + "duration_seconds", + "dz_switch_id", + "compass_zone_id", + "compass_x", + "compass_y", + "compass_z", + "return_zone_id", + "return_x", + "return_y", + "return_z", + "return_h", + "override_zone_in", + "zone_in_x", + "zone_in_y", + "zone_in_z", + "zone_in_h", + }; + } + + 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("dynamic_zone_templates"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + SelectColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static DynamicZoneTemplates NewEntity() + { + DynamicZoneTemplates entry{}; + + entry.id = 0; + entry.zone_id = 0; + entry.zone_version = 0; + entry.name = ""; + entry.min_players = 0; + entry.max_players = 0; + entry.duration_seconds = 0; + entry.dz_switch_id = 0; + entry.compass_zone_id = 0; + entry.compass_x = 0; + entry.compass_y = 0; + entry.compass_z = 0; + entry.return_zone_id = 0; + entry.return_x = 0; + entry.return_y = 0; + entry.return_z = 0; + entry.return_h = 0; + entry.override_zone_in = 0; + entry.zone_in_x = 0; + entry.zone_in_y = 0; + entry.zone_in_z = 0; + entry.zone_in_h = 0; + + return entry; + } + + static DynamicZoneTemplates GetDynamicZoneTemplatesEntry( + const std::vector &dynamic_zone_templatess, + int dynamic_zone_templates_id + ) + { + for (auto &dynamic_zone_templates : dynamic_zone_templatess) { + if (dynamic_zone_templates.id == dynamic_zone_templates_id) { + return dynamic_zone_templates; + } + } + + return NewEntity(); + } + + static DynamicZoneTemplates FindOne( + Database& db, + int dynamic_zone_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + dynamic_zone_templates_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + DynamicZoneTemplates entry{}; + + entry.id = atoi(row[0]); + entry.zone_id = atoi(row[1]); + entry.zone_version = atoi(row[2]); + entry.name = row[3] ? row[3] : ""; + entry.min_players = atoi(row[4]); + entry.max_players = atoi(row[5]); + entry.duration_seconds = atoi(row[6]); + entry.dz_switch_id = atoi(row[7]); + entry.compass_zone_id = atoi(row[8]); + entry.compass_x = static_cast(atof(row[9])); + entry.compass_y = static_cast(atof(row[10])); + entry.compass_z = static_cast(atof(row[11])); + entry.return_zone_id = atoi(row[12]); + entry.return_x = static_cast(atof(row[13])); + entry.return_y = static_cast(atof(row[14])); + entry.return_z = static_cast(atof(row[15])); + entry.return_h = static_cast(atof(row[16])); + entry.override_zone_in = atoi(row[17]); + entry.zone_in_x = static_cast(atof(row[18])); + entry.zone_in_y = static_cast(atof(row[19])); + entry.zone_in_z = static_cast(atof(row[20])); + entry.zone_in_h = static_cast(atof(row[21])); + + return entry; + } + + return NewEntity(); + } + + static int DeleteOne( + Database& db, + int dynamic_zone_templates_id + ) + { + auto results = db.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + dynamic_zone_templates_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + Database& db, + DynamicZoneTemplates dynamic_zone_templates_entry + ) + { + std::vector update_values; + + auto columns = Columns(); + + update_values.push_back(columns[1] + " = " + std::to_string(dynamic_zone_templates_entry.zone_id)); + update_values.push_back(columns[2] + " = " + std::to_string(dynamic_zone_templates_entry.zone_version)); + update_values.push_back(columns[3] + " = '" + Strings::Escape(dynamic_zone_templates_entry.name) + "'"); + update_values.push_back(columns[4] + " = " + std::to_string(dynamic_zone_templates_entry.min_players)); + update_values.push_back(columns[5] + " = " + std::to_string(dynamic_zone_templates_entry.max_players)); + update_values.push_back(columns[6] + " = " + std::to_string(dynamic_zone_templates_entry.duration_seconds)); + update_values.push_back(columns[7] + " = " + std::to_string(dynamic_zone_templates_entry.dz_switch_id)); + update_values.push_back(columns[8] + " = " + std::to_string(dynamic_zone_templates_entry.compass_zone_id)); + update_values.push_back(columns[9] + " = " + std::to_string(dynamic_zone_templates_entry.compass_x)); + update_values.push_back(columns[10] + " = " + std::to_string(dynamic_zone_templates_entry.compass_y)); + update_values.push_back(columns[11] + " = " + std::to_string(dynamic_zone_templates_entry.compass_z)); + update_values.push_back(columns[12] + " = " + std::to_string(dynamic_zone_templates_entry.return_zone_id)); + update_values.push_back(columns[13] + " = " + std::to_string(dynamic_zone_templates_entry.return_x)); + update_values.push_back(columns[14] + " = " + std::to_string(dynamic_zone_templates_entry.return_y)); + update_values.push_back(columns[15] + " = " + std::to_string(dynamic_zone_templates_entry.return_z)); + update_values.push_back(columns[16] + " = " + std::to_string(dynamic_zone_templates_entry.return_h)); + update_values.push_back(columns[17] + " = " + std::to_string(dynamic_zone_templates_entry.override_zone_in)); + update_values.push_back(columns[18] + " = " + std::to_string(dynamic_zone_templates_entry.zone_in_x)); + update_values.push_back(columns[19] + " = " + std::to_string(dynamic_zone_templates_entry.zone_in_y)); + update_values.push_back(columns[20] + " = " + std::to_string(dynamic_zone_templates_entry.zone_in_z)); + update_values.push_back(columns[21] + " = " + std::to_string(dynamic_zone_templates_entry.zone_in_h)); + + auto results = db.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + Strings::Implode(", ", update_values), + PrimaryKey(), + dynamic_zone_templates_entry.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static DynamicZoneTemplates InsertOne( + Database& db, + DynamicZoneTemplates dynamic_zone_templates_entry + ) + { + std::vector insert_values; + + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_version)); + insert_values.push_back("'" + Strings::Escape(dynamic_zone_templates_entry.name) + "'"); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.min_players)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.max_players)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.duration_seconds)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.dz_switch_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_zone_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_x)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_y)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_z)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_zone_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_x)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_y)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_z)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_h)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.override_zone_in)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_x)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_y)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_z)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_h)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + Strings::Implode(",", insert_values) + ) + ); + + if (results.Success()) { + dynamic_zone_templates_entry.id = results.LastInsertedID(); + return dynamic_zone_templates_entry; + } + + dynamic_zone_templates_entry = NewEntity(); + + return dynamic_zone_templates_entry; + } + + static int InsertMany( + Database& db, + std::vector dynamic_zone_templates_entries + ) + { + std::vector insert_chunks; + + for (auto &dynamic_zone_templates_entry: dynamic_zone_templates_entries) { + std::vector insert_values; + + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_version)); + insert_values.push_back("'" + Strings::Escape(dynamic_zone_templates_entry.name) + "'"); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.min_players)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.max_players)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.duration_seconds)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.dz_switch_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_zone_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_x)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_y)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.compass_z)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_zone_id)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_x)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_y)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_z)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.return_h)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.override_zone_in)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_x)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_y)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_z)); + insert_values.push_back(std::to_string(dynamic_zone_templates_entry.zone_in_h)); + + insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); + } + + std::vector insert_values; + + 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) { + DynamicZoneTemplates entry{}; + + entry.id = atoi(row[0]); + entry.zone_id = atoi(row[1]); + entry.zone_version = atoi(row[2]); + entry.name = row[3] ? row[3] : ""; + entry.min_players = atoi(row[4]); + entry.max_players = atoi(row[5]); + entry.duration_seconds = atoi(row[6]); + entry.dz_switch_id = atoi(row[7]); + entry.compass_zone_id = atoi(row[8]); + entry.compass_x = static_cast(atof(row[9])); + entry.compass_y = static_cast(atof(row[10])); + entry.compass_z = static_cast(atof(row[11])); + entry.return_zone_id = atoi(row[12]); + entry.return_x = static_cast(atof(row[13])); + entry.return_y = static_cast(atof(row[14])); + entry.return_z = static_cast(atof(row[15])); + entry.return_h = static_cast(atof(row[16])); + entry.override_zone_in = atoi(row[17]); + entry.zone_in_x = static_cast(atof(row[18])); + entry.zone_in_y = static_cast(atof(row[19])); + entry.zone_in_z = static_cast(atof(row[20])); + entry.zone_in_h = static_cast(atof(row[21])); + + all_entries.push_back(entry); + } + + return all_entries; + } + + static std::vector GetWhere(Database& db, 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) { + DynamicZoneTemplates entry{}; + + entry.id = atoi(row[0]); + entry.zone_id = atoi(row[1]); + entry.zone_version = atoi(row[2]); + entry.name = row[3] ? row[3] : ""; + entry.min_players = atoi(row[4]); + entry.max_players = atoi(row[5]); + entry.duration_seconds = atoi(row[6]); + entry.dz_switch_id = atoi(row[7]); + entry.compass_zone_id = atoi(row[8]); + entry.compass_x = static_cast(atof(row[9])); + entry.compass_y = static_cast(atof(row[10])); + entry.compass_z = static_cast(atof(row[11])); + entry.return_zone_id = atoi(row[12]); + entry.return_x = static_cast(atof(row[13])); + entry.return_y = static_cast(atof(row[14])); + entry.return_z = static_cast(atof(row[15])); + entry.return_h = static_cast(atof(row[16])); + entry.override_zone_in = atoi(row[17]); + entry.zone_in_x = static_cast(atof(row[18])); + entry.zone_in_y = static_cast(atof(row[19])); + entry.zone_in_z = static_cast(atof(row[20])); + entry.zone_in_h = static_cast(atof(row[21])); + + all_entries.push_back(entry); + } + + return all_entries; + } + + static int DeleteWhere(Database& db, 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); + } + +}; + +#endif //EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index e303290af..8baf94c89 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -44,6 +44,7 @@ public: int replay_timer_seconds; int request_timer_group; int request_timer_seconds; + int dz_template_id; int lock_activity_id; }; @@ -80,6 +81,7 @@ public: "replay_timer_seconds", "request_timer_group", "request_timer_seconds", + "dz_template_id", "lock_activity_id", }; } @@ -112,6 +114,7 @@ public: "replay_timer_seconds", "request_timer_group", "request_timer_seconds", + "dz_template_id", "lock_activity_id", }; } @@ -178,6 +181,7 @@ public: entry.replay_timer_seconds = 0; entry.request_timer_group = 0; entry.request_timer_seconds = 0; + entry.dz_template_id = 0; entry.lock_activity_id = -1; return entry; @@ -239,7 +243,8 @@ public: entry.replay_timer_seconds = atoi(row[22]); entry.request_timer_group = atoi(row[23]); entry.request_timer_seconds = atoi(row[24]); - entry.lock_activity_id = atoi(row[25]); + entry.dz_template_id = atoi(row[25]); + entry.lock_activity_id = atoi(row[26]); return entry; } @@ -298,7 +303,8 @@ public: update_values.push_back(columns[22] + " = " + std::to_string(tasks_entry.replay_timer_seconds)); update_values.push_back(columns[23] + " = " + std::to_string(tasks_entry.request_timer_group)); update_values.push_back(columns[24] + " = " + std::to_string(tasks_entry.request_timer_seconds)); - update_values.push_back(columns[25] + " = " + std::to_string(tasks_entry.lock_activity_id)); + update_values.push_back(columns[25] + " = " + std::to_string(tasks_entry.dz_template_id)); + update_values.push_back(columns[26] + " = " + std::to_string(tasks_entry.lock_activity_id)); auto results = db.QueryDatabase( fmt::format( @@ -345,6 +351,7 @@ public: insert_values.push_back(std::to_string(tasks_entry.replay_timer_seconds)); insert_values.push_back(std::to_string(tasks_entry.request_timer_group)); insert_values.push_back(std::to_string(tasks_entry.request_timer_seconds)); + insert_values.push_back(std::to_string(tasks_entry.dz_template_id)); insert_values.push_back(std::to_string(tasks_entry.lock_activity_id)); auto results = db.QueryDatabase( @@ -400,6 +407,7 @@ public: insert_values.push_back(std::to_string(tasks_entry.replay_timer_seconds)); insert_values.push_back(std::to_string(tasks_entry.request_timer_group)); insert_values.push_back(std::to_string(tasks_entry.request_timer_seconds)); + insert_values.push_back(std::to_string(tasks_entry.dz_template_id)); insert_values.push_back(std::to_string(tasks_entry.lock_activity_id)); insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); @@ -459,7 +467,8 @@ public: entry.replay_timer_seconds = atoi(row[22]); entry.request_timer_group = atoi(row[23]); entry.request_timer_seconds = atoi(row[24]); - entry.lock_activity_id = atoi(row[25]); + entry.dz_template_id = atoi(row[25]); + entry.lock_activity_id = atoi(row[26]); all_entries.push_back(entry); } @@ -509,7 +518,8 @@ public: entry.replay_timer_seconds = atoi(row[22]); entry.request_timer_group = atoi(row[23]); entry.request_timer_seconds = atoi(row[24]); - entry.lock_activity_id = atoi(row[25]); + entry.dz_template_id = atoi(row[25]); + entry.lock_activity_id = atoi(row[26]); all_entries.push_back(entry); } diff --git a/common/repositories/dynamic_zone_templates_repository.h b/common/repositories/dynamic_zone_templates_repository.h new file mode 100644 index 000000000..714762889 --- /dev/null +++ b/common/repositories/dynamic_zone_templates_repository.h @@ -0,0 +1,70 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2020 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 + * + */ + +#ifndef EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H +#define EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H + +#include "../database.h" +#include "../strings.h" +#include "base/base_dynamic_zone_templates_repository.h" + +class DynamicZoneTemplatesRepository: public BaseDynamicZoneTemplatesRepository { +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 + * + * DynamicZoneTemplatesRepository::GetByZoneAndVersion(int zone_id, int zone_version) + * DynamicZoneTemplatesRepository::GetWhereNeverExpires() + * DynamicZoneTemplatesRepository::GetWhereXAndY() + * DynamicZoneTemplatesRepository::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_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H diff --git a/common/servertalk.h b/common/servertalk.h index e0a791466..ee1ead831 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -244,6 +244,7 @@ #define ServerOP_ReloadVeteranRewards 0x4118 #define ServerOP_ReloadWorld 0x4119 #define ServerOP_ReloadZonePoints 0x4120 +#define ServerOP_ReloadDzTemplates 0x4121 #define ServerOP_CZDialogueWindow 0x4500 #define ServerOP_CZLDoNUpdate 0x4501 diff --git a/common/version.h b/common/version.h index 1d8180440..f7973dcb9 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9194 +#define CURRENT_BINARY_DATABASE_VERSION 9195 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9029 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 24d397417..b50807aee 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -448,6 +448,7 @@ 9192|2022_07_13_task_lock_activity.sql|SHOW COLUMNS FROM `tasks` LIKE 'lock_activity_id'|empty| 9193|2022_07_16_task_timer_groups.sql|SHOW COLUMNS FROM `tasks` LIKE 'replay_timer_group'|empty| 9194|2022_07_23_dz_switch_id.sql|SHOW COLUMNS FROM `doors` LIKE 'dz_switch_id'|empty| +9195|2022_07_23_dz_templates.sql|SHOW TABLES like 'dynamic_zone_templates'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2022_07_23_dz_templates.sql b/utils/sql/git/required/2022_07_23_dz_templates.sql new file mode 100644 index 000000000..272abf457 --- /dev/null +++ b/utils/sql/git/required/2022_07_23_dz_templates.sql @@ -0,0 +1,28 @@ +CREATE TABLE `dynamic_zone_templates` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `zone_id` int(11) NOT NULL DEFAULT 0, + `zone_version` int(11) NOT NULL DEFAULT 0, + `name` varchar(128) NOT NULL DEFAULT '', + `min_players` int(11) NOT NULL DEFAULT 0, + `max_players` int(11) NOT NULL DEFAULT 0, + `duration_seconds` int(11) NOT NULL DEFAULT 0, + `dz_switch_id` int(11) NOT NULL DEFAULT 0, + `compass_zone_id` int(11) NOT NULL DEFAULT 0, + `compass_x` float NOT NULL DEFAULT 0, + `compass_y` float NOT NULL DEFAULT 0, + `compass_z` float NOT NULL DEFAULT 0, + `return_zone_id` int(11) NOT NULL DEFAULT 0, + `return_x` float NOT NULL DEFAULT 0, + `return_y` float NOT NULL DEFAULT 0, + `return_z` float NOT NULL DEFAULT 0, + `return_h` float NOT NULL DEFAULT 0, + `override_zone_in` tinyint(4) NOT NULL DEFAULT 0, + `zone_in_x` float NOT NULL DEFAULT 0, + `zone_in_y` float NOT NULL DEFAULT 0, + `zone_in_z` float NOT NULL DEFAULT 0, + `zone_in_h` float NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 + +ALTER TABLE `tasks` + ADD COLUMN `dz_template_id` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `request_timer_seconds`; diff --git a/world/dynamic_zone_manager.cpp b/world/dynamic_zone_manager.cpp index e71ca5cdc..2bed2a97e 100644 --- a/world/dynamic_zone_manager.cpp +++ b/world/dynamic_zone_manager.cpp @@ -164,3 +164,13 @@ void DynamicZoneManager::Process() fmt::format("id IN ({})", fmt::join(dynamic_zone_ids, ","))); } } + +void DynamicZoneManager::LoadTemplates() +{ + m_dz_templates.clear(); + auto dz_templates = DynamicZoneTemplatesRepository::All(content_db); + for (const auto& dz_template : dz_templates) + { + m_dz_templates[dz_template.id] = dz_template; + } +} diff --git a/world/dynamic_zone_manager.h b/world/dynamic_zone_manager.h index ce59f62ee..8db6bfd06 100644 --- a/world/dynamic_zone_manager.h +++ b/world/dynamic_zone_manager.h @@ -2,6 +2,7 @@ #define WORLD_DYNAMIC_ZONE_MANAGER_H #include "../common/timer.h" +#include "../common/repositories/dynamic_zone_templates_repository.h" #include #include #include @@ -20,13 +21,16 @@ public: void CacheAllFromDatabase(); void CacheNewDynamicZone(ServerPacket* pack); DynamicZone* CreateNew(DynamicZone& dz_request, const std::vector& members); + void LoadTemplates(); void Process(); void PurgeExpiredDynamicZones(); + const auto& GetTemplates() const { return m_dz_templates; } std::unordered_map> dynamic_zone_cache; private: Timer m_process_throttle_timer{}; + std::unordered_map m_dz_templates; }; #endif diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index e28e86c08..fa91f647f 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -177,6 +177,8 @@ void SharedTaskManager::AttemptSharedTaskCreation( // check if task should immediately lock HandleCompletedActivities(&inserted); + LoadDynamicZoneTemplate(&inserted); + LogTasks( "[AttemptSharedTaskCreation] shared_task_id [{}] created successfully | task_id [{}] member_count [{}] activity_count [{}] current tasks in state [{}]", new_shared_task.GetDbSharedTask().id, @@ -1145,6 +1147,27 @@ void SharedTaskManager::CreateDynamicZone(SharedTask *shared_task, DynamicZone & } } +void SharedTaskManager::LoadDynamicZoneTemplate(SharedTask* s) +{ + const auto& task = s->GetTaskData(); + if (task.dz_template_id != 0) + { + auto it = dynamic_zone_manager.GetTemplates().find(task.dz_template_id); + if (it != dynamic_zone_manager.GetTemplates().end()) + { + DynamicZone dz(DynamicZoneType::Mission); + dz.LoadTemplate(it->second); + dz.SetMinPlayers(task.min_players); + dz.SetMaxPlayers(task.max_players); + if (task.duration > dz.GetDuration()) + { + dz.SetDuration(task.duration); + } + CreateDynamicZone(s, dz); + } + } +} + void SharedTaskManager::SendLeaderMessage(SharedTask *shared_task, int chat_type, const std::string &message) { if (!shared_task) { diff --git a/world/shared_task_manager.h b/world/shared_task_manager.h index 2f0164c7f..803a17245 100644 --- a/world/shared_task_manager.h +++ b/world/shared_task_manager.h @@ -123,6 +123,7 @@ protected: void ChooseNewLeader(SharedTask *s); bool HandleCompletedActivities(SharedTask* s); void HandleCompletedTask(SharedTask* s); + void LoadDynamicZoneTemplate(SharedTask* s); void SendSharedTaskMemberListToAllMembers(SharedTask *s); void SendSharedTaskMemberAddedToAllMembers(SharedTask *s, const std::string &player_name); void SendSharedTaskMemberRemovedToAllMembers(SharedTask *s, const std::string &player_name); diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 2e4b8d4ea..78f413bbc 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -408,6 +408,7 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv) database.PurgeExpiredInstances(); LogInfo("Loading dynamic zones"); + dynamic_zone_manager.LoadTemplates(); dynamic_zone_manager.CacheAllFromDatabase(); LogInfo("Loading char create info"); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 5238628ce..04549b5b8 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "queryserv.h" #include "world_store.h" #include "dynamic_zone.h" +#include "dynamic_zone_manager.h" #include "expedition_message.h" #include "shared_task_world_messaging.h" #include "../common/shared_tasks.h" @@ -1352,6 +1353,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { zoneserver_list.SendPacket(pack); break; } + case ServerOP_ReloadDzTemplates: { + dynamic_zone_manager.LoadTemplates(); + zoneserver_list.SendPacket(pack); + break; + } case ServerOP_ChangeSharedMem: { auto hotfix_name = std::string((char*) pack->pBuffer); diff --git a/zone/client.cpp b/zone/client.cpp index d5a848f2b..f1986b7f0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9842,6 +9842,19 @@ Expedition* Client::CreateExpedition( return Expedition::TryCreate(this, dz, disable_messages); } +Expedition* Client::CreateExpeditionFromTemplate(uint32_t dz_template_id) +{ + Expedition* expedition = nullptr; + auto it = zone->dz_template_cache.find(dz_template_id); + if (it != zone->dz_template_cache.end()) + { + DynamicZone dz(DynamicZoneType::Expedition); + dz.LoadTemplate(it->second); + expedition = Expedition::TryCreate(this, dz, false); + } + return expedition; +} + void Client::CreateTaskDynamicZone(int task_id, DynamicZone& dz_request) { if (task_state) @@ -11332,6 +11345,9 @@ void Client::SendReloadCommandMessages() { ).c_str() ); + auto dztemplates_link = Saylink::Create("#reload dztemplates", false, "#reload dztemplates"); + Message(Chat::White, fmt::format("Usage: {} - Reloads Dynamic Zone Templates globally", dztemplates_link).c_str()); + auto ground_spawns_link = Saylink::Create( "#reload ground_spawns", false, diff --git a/zone/client.h b/zone/client.h index 4391e9c94..a55f6efcd 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1389,6 +1389,7 @@ public: Expedition* CreateExpedition(const std::string& zone_name, uint32 version, uint32 duration, const std::string& expedition_name, uint32 min_players, uint32 max_players, bool disable_messages = false); + Expedition* CreateExpeditionFromTemplate(uint32_t dz_template_id); Expedition* GetExpedition() const; uint32 GetExpeditionID() const { return m_expedition_id; } const ExpeditionLockoutTimer* GetExpeditionLockout( diff --git a/zone/gm_commands/reload.cpp b/zone/gm_commands/reload.cpp index e5ab81538..0335fb476 100644 --- a/zone/gm_commands/reload.cpp +++ b/zone/gm_commands/reload.cpp @@ -13,6 +13,7 @@ void command_reload(Client *c, const Seperator *sep) bool is_blocked_spells = !strcasecmp(sep->arg[1], "blocked_spells"); bool is_content_flags = !strcasecmp(sep->arg[1], "content_flags"); bool is_doors = !strcasecmp(sep->arg[1], "doors"); + bool is_dztemplates = !strcasecmp(sep->arg[1], "dztemplates"); bool is_ground_spawns = !strcasecmp(sep->arg[1], "ground_spawns"); bool is_level_mods = !strcasecmp(sep->arg[1], "level_mods"); bool is_logs = !strcasecmp(sep->arg[1], "logs"); @@ -38,6 +39,7 @@ void command_reload(Client *c, const Seperator *sep) !is_blocked_spells && !is_content_flags && !is_doors && + !is_dztemplates && !is_ground_spawns && !is_level_mods && !is_logs && @@ -78,6 +80,9 @@ void command_reload(Client *c, const Seperator *sep) } else if (is_doors) { c->Message(Chat::White, "Attempting to reload Doors globally."); pack = new ServerPacket(ServerOP_ReloadDoors, 0); + } else if (is_dztemplates) { + c->Message(Chat::White, "Attempting to reload Dynamic Zone Templates globally."); + pack = new ServerPacket(ServerOP_ReloadDzTemplates, 0); } else if (is_ground_spawns) { c->Message(Chat::White, "Attempting to reload Ground Spawns globally."); pack = new ServerPacket(ServerOP_ReloadGroundSpawns, 0); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 869afc44d..b09253635 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1973,6 +1973,11 @@ Lua_Expedition Lua_Client::CreateExpedition(std::string zone_name, uint32 versio return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages); } +Lua_Expedition Lua_Client::CreateExpeditionFromTemplate(uint32_t dz_template_id) { + Lua_Safe_Call_Class(Lua_Expedition); + return self->CreateExpeditionFromTemplate(dz_template_id); +} + Lua_Expedition Lua_Client::GetExpedition() { Lua_Safe_Call_Class(Lua_Expedition); return self->GetExpedition(); @@ -2604,6 +2609,7 @@ luabind::scope lua_register_client() { .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition) + .def("CreateExpeditionFromTemplate", &Lua_Client::CreateExpeditionFromTemplate) .def("CreateTaskDynamicZone", &Lua_Client::CreateTaskDynamicZone) .def("DecreaseByID", (bool(Lua_Client::*)(uint32,int))&Lua_Client::DecreaseByID) .def("DeleteItemInInventory", (void(Lua_Client::*)(int,int))&Lua_Client::DeleteItemInInventory) diff --git a/zone/lua_client.h b/zone/lua_client.h index 7520a96db..d6a21c7da 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -433,6 +433,7 @@ public: Lua_Expedition CreateExpedition(luabind::object expedition_info); Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players); Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages); + Lua_Expedition CreateExpeditionFromTemplate(uint32_t dz_template_id); Lua_Expedition GetExpedition(); luabind::object GetExpeditionLockouts(lua_State* L); luabind::object GetExpeditionLockouts(lua_State* L, std::string expedition_name); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 16186994d..83d1b78f5 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1804,6 +1804,11 @@ Expedition* Perl_Client_CreateExpedition(Client* self, std::string zone_name, ui return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages); } +Expedition* Perl_Client_CreateExpeditionFromTemplate(Client* self, uint32_t dz_template_id) +{ + return self->CreateExpeditionFromTemplate(dz_template_id); +} + void Perl_Client_CreateTaskDynamicZone(Client* self, int task_id, perl::reference table_ref) { perl::hash table = table_ref; @@ -2452,6 +2457,7 @@ void perl_register_client() package.add("CreateExpedition", (Expedition*(*)(Client*, perl::reference))&Perl_Client_CreateExpedition); package.add("CreateExpedition", (Expedition*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32))&Perl_Client_CreateExpedition); package.add("CreateExpedition", (Expedition*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32, bool))&Perl_Client_CreateExpedition); + package.add("CreateExpeditionFromTemplate", &Perl_Client_CreateExpeditionFromTemplate); package.add("CreateTaskDynamicZone", &Perl_Client_CreateTaskDynamicZone); package.add("DecreaseByID", &Perl_Client_DecreaseByID); package.add("DeleteItemInInventory", (void(*)(Client*, int16))&Perl_Client_DeleteItemInInventory); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 980d71d23..f760f98d7 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1929,6 +1929,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) entity_list.RespawnAllDoors(); break; } + case ServerOP_ReloadDzTemplates: + { + if (zone) + { + zone->SendReloadMessage("Dynamic Zone Templates"); + zone->LoadDynamicZoneTemplates(); + } + break; + } case ServerOP_ReloadGroundSpawns: { zone->SendReloadMessage("Ground Spawns"); diff --git a/zone/zone.cpp b/zone/zone.cpp index aafb951d0..aaf7756f9 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1192,6 +1192,8 @@ bool Zone::Init(bool is_static) { petition_list.ClearPetitions(); petition_list.ReadDatabase(); + LoadDynamicZoneTemplates(); + LogInfo("Loading dynamic zones"); DynamicZone::CacheAllFromDatabase(); @@ -2812,3 +2814,13 @@ void Zone::SendDiscordMessage(const std::string& webhook_name, const std::string LogDiscord("[SendDiscordMessage] Did not find valid webhook by webhook name [{}]", webhook_name); } } + +void Zone::LoadDynamicZoneTemplates() +{ + dz_template_cache.clear(); + auto dz_templates = DynamicZoneTemplatesRepository::All(content_db); + for (const auto& dz_template : dz_templates) + { + dz_template_cache[dz_template.id] = dz_template; + } +} diff --git a/zone/zone.h b/zone/zone.h index 5c8efe657..11884892b 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -37,6 +37,7 @@ #include "global_loot_manager.h" #include "queryserv.h" #include "../common/discord/discord.h" +#include "../common/repositories/dynamic_zone_templates_repository.h" class DynamicZone; @@ -227,6 +228,7 @@ public: std::unordered_map> dynamic_zone_cache; std::unordered_map> expedition_cache; + std::unordered_map dz_template_cache; time_t weather_timer; Timer spawn2_timer; @@ -267,6 +269,7 @@ public: void LoadAdventureFlavor(); void LoadAlternateAdvancement(); void LoadAlternateCurrencies(); + void LoadDynamicZoneTemplates(); void LoadZoneBlockedSpells(); void LoadLDoNTrapEntries(); void LoadLDoNTraps();