diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index deeaa094b..54e5b549b 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7055,7 +7055,22 @@ CREATE INDEX idx_expires ON data_buckets (expires); )", .content_schema_update = false }, + ManifestEntry{ + .version = 9320, + .description = "2025_03_23_add_respawn_times_expire_at.sql", + .check = "SHOW COLUMNS FROM `respawn_times` LIKE 'expire_at'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `respawn_times` +ADD COLUMN `expire_at` int(11) UNSIGNED NULL DEFAULT 0 AFTER `duration`; +UPDATE respawn_times set expire_at = `start` + `duration`; -- backfill existing data + +CREATE INDEX `idx_expire_at` ON `respawn_times` (`expire_at`); +)", + .content_schema_update = false + }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/repositories/base/base_respawn_times_repository.h b/common/repositories/base/base_respawn_times_repository.h index 94d5526a8..303296c10 100644 --- a/common/repositories/base/base_respawn_times_repository.h +++ b/common/repositories/base/base_respawn_times_repository.h @@ -19,10 +19,11 @@ class BaseRespawnTimesRepository { public: struct RespawnTimes { - int32_t id; - int32_t start; - int32_t duration; - int16_t instance_id; + int32_t id; + int32_t start; + int32_t duration; + uint32_t expire_at; + int16_t instance_id; }; static std::string PrimaryKey() @@ -36,6 +37,7 @@ public: "id", "start", "duration", + "expire_at", "instance_id", }; } @@ -46,6 +48,7 @@ public: "id", "start", "duration", + "expire_at", "instance_id", }; } @@ -90,6 +93,7 @@ public: e.id = 0; e.start = 0; e.duration = 0; + e.expire_at = 0; e.instance_id = 0; return e; @@ -130,7 +134,8 @@ public: e.id = row[0] ? static_cast(atoi(row[0])) : 0; e.start = row[1] ? static_cast(atoi(row[1])) : 0; e.duration = row[2] ? static_cast(atoi(row[2])) : 0; - e.instance_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.expire_at = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; return e; } @@ -167,7 +172,8 @@ public: v.push_back(columns[0] + " = " + std::to_string(e.id)); v.push_back(columns[1] + " = " + std::to_string(e.start)); v.push_back(columns[2] + " = " + std::to_string(e.duration)); - v.push_back(columns[3] + " = " + std::to_string(e.instance_id)); + v.push_back(columns[3] + " = " + std::to_string(e.expire_at)); + v.push_back(columns[4] + " = " + std::to_string(e.instance_id)); auto results = db.QueryDatabase( fmt::format( @@ -192,6 +198,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.start)); v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.expire_at)); v.push_back(std::to_string(e.instance_id)); auto results = db.QueryDatabase( @@ -225,6 +232,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.start)); v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.expire_at)); v.push_back(std::to_string(e.instance_id)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); @@ -262,7 +270,8 @@ public: e.id = row[0] ? static_cast(atoi(row[0])) : 0; e.start = row[1] ? static_cast(atoi(row[1])) : 0; e.duration = row[2] ? static_cast(atoi(row[2])) : 0; - e.instance_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.expire_at = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; all_entries.push_back(e); } @@ -290,7 +299,8 @@ public: e.id = row[0] ? static_cast(atoi(row[0])) : 0; e.start = row[1] ? static_cast(atoi(row[1])) : 0; e.duration = row[2] ? static_cast(atoi(row[2])) : 0; - e.instance_id = row[3] ? static_cast(atoi(row[3])) : 0; + e.expire_at = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.instance_id = row[4] ? static_cast(atoi(row[4])) : 0; all_entries.push_back(e); } @@ -368,6 +378,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.start)); v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.expire_at)); v.push_back(std::to_string(e.instance_id)); auto results = db.QueryDatabase( @@ -394,6 +405,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back(std::to_string(e.start)); v.push_back(std::to_string(e.duration)); + v.push_back(std::to_string(e.expire_at)); v.push_back(std::to_string(e.instance_id)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); diff --git a/common/repositories/respawn_times_repository.h b/common/repositories/respawn_times_repository.h index 05c321f28..3f2ddfa8b 100644 --- a/common/repositories/respawn_times_repository.h +++ b/common/repositories/respawn_times_repository.h @@ -8,47 +8,11 @@ class RespawnTimesRepository: public BaseRespawnTimesRepository { 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 - * - * RespawnTimesRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * RespawnTimesRepository::GetWhereNeverExpires() - * RespawnTimesRepository::GetWhereXAndY() - * RespawnTimesRepository::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 static void ClearExpiredRespawnTimers(Database& db) { db.QueryDatabase( fmt::format( - "DELETE FROM `{}` WHERE (`start` + `duration`) < UNIX_TIMESTAMP(NOW())", + "DELETE FROM `{}` WHERE `expire_at` < UNIX_TIMESTAMP(NOW())", TableName() ) ); diff --git a/common/version.h b/common/version.h index b6c37fe06..a86ce925d 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 9319 +#define CURRENT_BINARY_DATABASE_VERSION 9320 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #endif diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 543d8ffa7..2dee4d439 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -164,6 +164,7 @@ void ZoneDatabase::UpdateRespawnTime(uint32 spawn2_id, uint16 instance_id, uint3 .id = static_cast(spawn2_id), .start = static_cast(current_time), .duration = static_cast(time_left), + .expire_at = current_time + time_left, .instance_id = static_cast(instance_id) } );