From bb6047248ace92bd5482fbbcb9d1c9a9c8194a0b Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Sat, 28 Mar 2020 18:47:53 -0300 Subject: [PATCH] fix(Calendar/Packets): add additional validation when creating events (#2799) --- src/server/game/Calendar/CalendarMgr.cpp | 104 +++++++++++++------ src/server/game/Calendar/CalendarMgr.h | 23 +++- src/server/game/Handlers/CalendarHandler.cpp | 101 ++++++++++++++++-- src/server/game/Server/WorldSession.cpp | 3 +- src/server/game/Server/WorldSession.h | 15 ++- src/server/game/World/World.cpp | 40 +++++++ src/server/game/World/World.h | 19 ++-- src/server/worldserver/worldserver.conf.dist | 8 ++ 8 files changed, 250 insertions(+), 63 deletions(-) diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index 5703ff96b..5a863eece 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -14,7 +14,9 @@ CalendarInvite::~CalendarInvite() { - sCalendarMgr->FreeInviteId(_inviteId); + // Free _inviteId only if it's a real invite and not just a pre-invite or guild announcement + if (_inviteId != 0 && _eventId != 0) + sCalendarMgr->FreeInviteId(_inviteId); } CalendarEvent::~CalendarEvent() @@ -141,15 +143,25 @@ void CalendarMgr::AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite } } -CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, uint64 remover) +void CalendarMgr::RemoveEvent(uint64 eventId, uint64 remover) { - CalendarEventStore::iterator current; - CalendarEvent* calendarEvent = GetEvent(eventId, ¤t); + CalendarEvent* calendarEvent = GetEvent(eventId); if (!calendarEvent) { SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID); - return _events.end(); + return; + } + + RemoveEvent(calendarEvent, remover); +} + +void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, uint64 remover) +{ + if (!calendarEvent) + { + SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID); + return; } SendCalendarEventRemovedAlert(*calendarEvent); @@ -158,7 +170,7 @@ CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, uint64 rem PreparedStatement* stmt; MailDraft mail(calendarEvent->BuildCalendarMailSubject(remover), calendarEvent->BuildCalendarMailBody()); - CalendarInviteStore& eventInvites = _invites[eventId]; + CalendarInviteStore& eventInvites = _invites[calendarEvent->GetEventId()]; for (size_t i = 0; i < eventInvites.size(); ++i) { CalendarInvite* invite = eventInvites[i]; @@ -174,16 +186,16 @@ CalendarEventStore::iterator CalendarMgr::RemoveEvent(uint64 eventId, uint64 rem delete invite; } - _invites.erase(eventId); + _invites.erase(calendarEvent->GetEventId()); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CALENDAR_EVENT); - stmt->setUInt64(0, eventId); + stmt->setUInt64(0, calendarEvent->GetEventId()); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); delete calendarEvent; - current = _events.erase(current); - return current; + _events.erase(calendarEvent); + return; } void CalendarMgr::RemoveInvite(uint64 inviteId, uint64 eventId, uint64 /*remover*/) @@ -260,12 +272,13 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(uint64 guid) { for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) { - if ((*itr)->GetCreatorGUID() == guid) + CalendarEvent* event = *itr; + ++itr; + if (event->GetCreatorGUID() == guid) { - itr = RemoveEvent((*itr)->GetEventId(), 0); // don't send mail if removing a character + RemoveEvent(event, 0); continue; } - ++itr; } CalendarInviteStore playerInvites = GetPlayerInvites(guid); @@ -275,15 +288,9 @@ void CalendarMgr::RemoveAllPlayerEventsAndInvites(uint64 guid) void CalendarMgr::RemovePlayerGuildEventsAndSignups(uint64 guid, uint32 guildId) { - for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) - { + for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) if ((*itr)->GetCreatorGUID() == guid && ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement())) - { - itr = RemoveEvent((*itr)->GetEventId(), guid); - continue; - } - ++itr; - } + RemoveEvent((*itr)->GetEventId(), guid); CalendarInviteStore playerInvites = GetPlayerInvites(guid); for (CalendarInviteStore::const_iterator itr = playerInvites.begin(); itr != playerInvites.end(); ++itr) @@ -292,17 +299,13 @@ void CalendarMgr::RemovePlayerGuildEventsAndSignups(uint64 guid, uint32 guildId) RemoveInvite((*itr)->GetInviteId(), (*itr)->GetEventId(), guid); } -CalendarEvent* CalendarMgr::GetEvent(uint64 eventId, CalendarEventStore::iterator* it) +CalendarEvent* CalendarMgr::GetEvent(uint64 eventId) { for (CalendarEventStore::iterator itr = _events.begin(); itr != _events.end(); ++itr) if ((*itr)->GetEventId() == eventId) - { - if (it) - *it = itr; return *itr; - } - return NULL; + return nullptr; } CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) const @@ -315,7 +318,7 @@ CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) const #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) sLog->outDebug(LOG_FILTER_UNITS, "CalendarMgr::GetInvite: [" UI64FMTD "] not found!", inviteId); #endif - return NULL; + return nullptr; } void CalendarMgr::FreeEventId(uint64 id) @@ -354,6 +357,44 @@ uint64 CalendarMgr::GetFreeInviteId() return inviteId; } +void CalendarMgr::DeleteOldEvents() +{ + time_t oldEventsTime = time(nullptr) - CALENDAR_OLD_EVENTS_DELETION_TIME; + + for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();) + { + CalendarEvent* event = *itr; + ++itr; + if (event->GetEventTime() < oldEventsTime) + RemoveEvent(event, 0); + } +} + +CalendarEventStore CalendarMgr::GetEventsCreatedBy(uint64 guid, bool includeGuildEvents) +{ + CalendarEventStore result; + for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) + if ((*itr)->GetCreatorGUID() == guid && (includeGuildEvents || (!(*itr)->IsGuildEvent() && !(*itr)->IsGuildAnnouncement()))) + result.insert(*itr); + + return result; +} + +CalendarEventStore CalendarMgr::GetGuildEvents(uint32 guildId) +{ + CalendarEventStore result; + + if (!guildId) + return result; + + for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) + if ((*itr)->IsGuildEvent() || (*itr)->IsGuildAnnouncement()) + if ((*itr)->GetGuildId() == guildId) + result.insert(*itr); + + return result; +} + CalendarEventStore CalendarMgr::GetPlayerEvents(uint64 guid) { CalendarEventStore events; @@ -365,9 +406,10 @@ CalendarEventStore CalendarMgr::GetPlayerEvents(uint64 guid) events.insert(event); if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(guid)) - for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) - if ((*itr)->GetGuildId() == player->GetGuildId()) - events.insert(*itr); + if (player->GetGuildId()) + for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr) + if ((*itr)->GetGuildId() == player->GetGuildId()) + events.insert(*itr); return events; } diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h index 3017bdbb0..4c2ee3409 100644 --- a/src/server/game/Calendar/CalendarMgr.h +++ b/src/server/game/Calendar/CalendarMgr.h @@ -110,9 +110,14 @@ enum CalendarError CALENDAR_ERROR_NO_MODERATOR = 40 }; -#define CALENDAR_MAX_EVENTS 30 -#define CALENDAR_MAX_GUILD_EVENTS 100 -#define CALENDAR_MAX_INVITES 100 +enum CalendarLimits +{ + CALENDAR_MAX_EVENTS = 30, + CALENDAR_MAX_GUILD_EVENTS = 100, + CALENDAR_MAX_INVITES = 100, + CALENDAR_CREATE_EVENT_COOLDOWN = 5, + CALENDAR_OLD_EVENTS_DELETION_TIME = 1 * MONTH, +}; struct CalendarInvite { @@ -235,6 +240,9 @@ struct CalendarEvent bool IsGuildEvent() const { return _flags & CALENDAR_FLAG_GUILD_EVENT; } bool IsGuildAnnouncement() const { return _flags & CALENDAR_FLAG_WITHOUT_INVITES; } + static bool IsGuildEvent(uint32 flags) { return (flags & CALENDAR_FLAG_GUILD_EVENT) != 0; } + static bool IsGuildAnnouncement(uint32 flags) { return (flags & CALENDAR_FLAG_WITHOUT_INVITES) != 0; } + std::string BuildCalendarMailSubject(uint64 remover) const; std::string BuildCalendarMailBody() const; @@ -273,9 +281,11 @@ class CalendarMgr void LoadFromDB(); - CalendarEvent* GetEvent(uint64 eventId, CalendarEventStore::iterator* it = NULL); + CalendarEvent* GetEvent(uint64 eventId); CalendarEventStore const& GetEvents() const { return _events; } + CalendarEventStore GetEventsCreatedBy(uint64 guid, bool includeGuildEvents = false); CalendarEventStore GetPlayerEvents(uint64 guid); + CalendarEventStore GetGuildEvents(uint32 guildId); CalendarInvite* GetInvite(uint64 inviteId) const; CalendarEventInviteStore const& GetInvites() const { return _invites; } @@ -287,10 +297,13 @@ class CalendarMgr void FreeInviteId(uint64 id); uint64 GetFreeInviteId(); + void DeleteOldEvents(); + uint32 GetPlayerNumPending(uint64 guid); void AddEvent(CalendarEvent* calendarEvent, CalendarSendEventType sendType); - CalendarEventStore::iterator RemoveEvent(uint64 eventId, uint64 remover); + void RemoveEvent(uint64 eventId, uint64 remover); + void RemoveEvent(CalendarEvent* calendarEvent, uint64 remover); void UpdateEvent(CalendarEvent* calendarEvent); void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite); diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index a9aaf9c66..51b486829 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -239,7 +239,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData >> flags; // prevent attacks with non-utf8 chars -> with multiple packets it will hang up the db due to errors. - if (!validUtf8String(recvData, title, "create", guid) || !validUtf8String(recvData, description, "create", guid)) + if (!validUtf8String(recvData, title, "create", guid) || title.size() > 31 || !validUtf8String(recvData, description, "create", guid) || description.size() > 255) return; // prevent events in the past @@ -247,9 +247,49 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) if (time_t(eventPackedTime) < (time(NULL) - time_t(86400L))) { recvData.rfinish(); + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_PASSED); return; } + // If the event is a guild event, check if the player is in a guild + if (CalendarEvent::IsGuildEvent(flags) || CalendarEvent::IsGuildAnnouncement(flags)) + { + if (!_player->GetGuildId()) + { + recvData.rfinish(); + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + } + + // Check if the player reached the max number of events allowed to create + if (CalendarEvent::IsGuildEvent(flags) || CalendarEvent::IsGuildAnnouncement(flags)) + { + if (sCalendarMgr->GetGuildEvents(_player->GetGuildId()).size() >= CALENDAR_MAX_GUILD_EVENTS) + { + recvData.rfinish(); + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_GUILD_EVENTS_EXCEEDED); + return; + } + } + else + { + if (sCalendarMgr->GetEventsCreatedBy(guid).size() >= CALENDAR_MAX_EVENTS) + { + recvData.rfinish(); + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENTS_EXCEEDED); + return; + } + } + + if (GetCalendarEventCreationCooldown() > time(nullptr)) + { + recvData.rfinish(); + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_INTERNAL); + return; + } + SetCalendarEventCreationCooldown(time(nullptr) + CALENDAR_CREATE_EVENT_COOLDOWN); + CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description); @@ -265,13 +305,10 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) } else { - // client limits the amount of players to be invited to 100 - const uint32 MaxPlayerInvites = 100; - uint32 inviteCount; - uint64 invitee[MaxPlayerInvites]; - uint8 status[MaxPlayerInvites]; - uint8 rank[MaxPlayerInvites]; + uint64 invitee[CALENDAR_MAX_INVITES]; + uint8 status[CALENDAR_MAX_INVITES]; + uint8 rank[CALENDAR_MAX_INVITES]; memset(invitee, 0, sizeof(invitee)); memset(status, 0, sizeof(status)); @@ -281,7 +318,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) { recvData >> inviteCount; - for (uint32 i = 0; i < inviteCount && i < MaxPlayerInvites; ++i) + for (uint32 i = 0; i < inviteCount && i < CALENDAR_MAX_INVITES; ++i) { recvData.readPackGUID(invitee[i]); recvData >> status[i] >> rank[i]; @@ -298,7 +335,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) if (inviteCount > 1) trans = CharacterDatabase.BeginTransaction(); - for (uint32 i = 0; i < inviteCount && i < MaxPlayerInvites; ++i) + for (uint32 i = 0; i < inviteCount && i < CALENDAR_MAX_INVITES; ++i) { // 946684800 is 01/01/2000 00:00:00 - default response time CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent->GetEventId(), invitee[i], guid, 946684800, CalendarInviteStatus(status[i]), CalendarModerationRank(rank[i]), ""); @@ -335,7 +372,7 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recvData) recvData >> flags; // prevent attacks with non-utf8 chars -> with multiple packets it will hang up the db due to errors. - if (!validUtf8String(recvData, title, "update", guid) || !validUtf8String(recvData, description, "update", guid)) + if (!validUtf8String(recvData, title, "update", guid) || title.size() > 31 || !validUtf8String(recvData, description, "update", guid) || description.size() > 255) return; // prevent events in the past @@ -400,11 +437,55 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket& recvData) if (time_t(eventTime) < (time(NULL) - time_t(86400L))) { recvData.rfinish(); + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_PASSED); return; } if (CalendarEvent* oldEvent = sCalendarMgr->GetEvent(eventId)) { + // Ensure that the player has access to the event + if (oldEvent->IsGuildEvent() || oldEvent->IsGuildAnnouncement()) + { + if (oldEvent->GetGuildId() != _player->GetGuildId()) + { + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_INVALID); + return; + } + } + else + { + if (oldEvent->GetCreatorGUID() != guid) + { + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_INVALID); + return; + } + } + + // Check if the player reached the max number of events allowed to create + if (oldEvent->IsGuildEvent() || oldEvent->IsGuildAnnouncement()) + { + if (sCalendarMgr->GetGuildEvents(_player->GetGuildId()).size() >= CALENDAR_MAX_GUILD_EVENTS) + { + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_GUILD_EVENTS_EXCEEDED); + return; + } + } + else + { + if (sCalendarMgr->GetEventsCreatedBy(guid).size() >= CALENDAR_MAX_EVENTS) + { + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENTS_EXCEEDED); + return; + } + } + + if (GetCalendarEventCreationCooldown() > time(nullptr)) + { + sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_INTERNAL); + return; + } + SetCalendarEventCreationCooldown(time(nullptr) + CALENDAR_CREATE_EVENT_COOLDOWN); + CalendarEvent* newEvent = new CalendarEvent(*oldEvent, sCalendarMgr->GetFreeEventId()); newEvent->SetEventTime(time_t(eventTime)); sCalendarMgr->AddEvent(newEvent, CALENDAR_SENDTYPE_COPY); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 8a22b5d88..12c6aebbf 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -113,7 +113,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 recruiterId(recruiter), isRecruiter(isARecruiter), m_currentBankerGUID(0), - timeWhoCommandAllowed(0) + timeWhoCommandAllowed(0), + _calendarEventCreationCooldown(0) { memset(m_Tutorials, 0, sizeof(m_Tutorials)); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 5bd4f0759..322173c44 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -317,8 +317,6 @@ class WorldSession m_TutorialsChanged = true; } } - //used with item_page table - bool SendItemInfo(uint32 itemid, WorldPacket data); //auction void SendAuctionHello(uint64 guid, Creature* unit); void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0); @@ -381,6 +379,10 @@ class WorldSession uint32 GetRecruiterId() const { return recruiterId; } bool IsARecruiter() const { return isRecruiter; } + // Packets cooldown + time_t GetCalendarEventCreationCooldown() const { return _calendarEventCreationCooldown; } + void SetCalendarEventCreationCooldown(time_t cooldown) { _calendarEventCreationCooldown = cooldown; } + public: // opcodes handlers void Handle_NULL(WorldPacket& recvPacket); // not used @@ -405,7 +407,6 @@ class WorldSession // new void HandleMoveUnRootAck(WorldPacket& recvPacket); void HandleMoveRootAck(WorldPacket& recvPacket); - void HandleLookingForGroup(WorldPacket& recvPacket); // new inspect void HandleInspectOpcode(WorldPacket& recvPacket); @@ -433,8 +434,6 @@ class WorldSession void HandleMoveTeleportAck(WorldPacket& recvPacket); void HandleForceSpeedChangeAck(WorldPacket& recvData); - void HandlePingOpcode(WorldPacket& recvPacket); - void HandleAuthSessionOpcode(WorldPacket& recvPacket); void HandleRepopRequestOpcode(WorldPacket& recvPacket); void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket); void HandleLootMoneyOpcode(WorldPacket& recvPacket); @@ -484,7 +483,6 @@ class WorldSession void HandleSetActionButtonOpcode(WorldPacket& recvPacket); void HandleGameObjectUseOpcode(WorldPacket& recPacket); - void HandleMeetingStoneInfo(WorldPacket& recPacket); void HandleGameobjectReportUse(WorldPacket& recvPacket); void HandleNameQueryOpcode(WorldPacket& recvPacket); @@ -511,7 +509,6 @@ class WorldSession void HandleBattlefieldStatusOpcode(WorldPacket& recvData); void HandleGroupInviteOpcode(WorldPacket& recvPacket); - //void HandleGroupCancelOpcode(WorldPacket& recvPacket); void HandleGroupAcceptOpcode(WorldPacket& recvPacket); void HandleGroupDeclineOpcode(WorldPacket& recvPacket); void HandleGroupUninviteOpcode(WorldPacket& recvPacket); @@ -631,7 +628,6 @@ class WorldSession void HandleQueryNextMailTime(WorldPacket& recvData); void HandleCancelChanneling(WorldPacket& recvData); - void SendItemPageInfo(ItemTemplate* itemProto); void HandleSplitItemOpcode(WorldPacket& recvPacket); void HandleSwapInvItemOpcode(WorldPacket& recvPacket); void HandleDestroyItemOpcode(WorldPacket& recvPacket); @@ -713,7 +709,6 @@ class WorldSession void HandleChannelBan(WorldPacket& recvPacket); void HandleChannelUnban(WorldPacket& recvPacket); void HandleChannelAnnouncements(WorldPacket& recvPacket); - void HandleChannelModerate(WorldPacket& recvPacket); void HandleChannelDeclineInvite(WorldPacket& recvPacket); void HandleChannelDisplayListQuery(WorldPacket& recvPacket); void HandleGetChannelMemberCount(WorldPacket& recvPacket); @@ -1041,6 +1036,8 @@ class WorldSession uint32 _offlineTime; bool _kicked; bool _shouldSetOfflineInDB; + // Packets cooldown + time_t _calendarEventCreationCooldown; }; #endif /// @} diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a795d9da2..00e01f3c9 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -111,6 +111,7 @@ World::World() m_NextWeeklyQuestReset = 0; m_NextMonthlyQuestReset = 0; m_NextRandomBGReset = 0; + m_NextCalendarOldEventsDeletionTime = 0; m_NextGuildReset = 0; m_defaultDbcLocale = LOCALE_enUS; @@ -1071,6 +1072,13 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = 6; } + m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] = sConfigMgr->GetIntDefault("Calendar.DeleteOldEventsHour", 6); + if (m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] > 23) + { + sLog->outError("Calendar.DeleteOldEventsHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR]); + m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] = 6; + } + m_int_configs[CONFIG_GUILD_RESET_HOUR] = sConfigMgr->GetIntDefault("Guild.ResetHour", 6); if (m_int_configs[CONFIG_GUILD_RESET_HOUR] > 23) { @@ -1964,6 +1972,9 @@ void World::SetInitialWorldSettings() sLog->outString("Calculate random battleground reset time..." ); InitRandomBGResetTime(); + sLog->outString("Calculate deletion of old calendar events time..."); + InitCalendarOldEventsDeletionTime(); + sLog->outString("Calculate Guild cap reset time..."); InitGuildResetTime(); @@ -2165,6 +2176,9 @@ void World::Update(uint32 diff) if (m_gameTime > m_NextRandomBGReset) ResetRandomBG(); + if (m_gameTime > m_NextCalendarOldEventsDeletionTime) + CalendarDeleteOldEvents(); + if (m_gameTime > m_NextGuildReset) ResetGuildCap(); @@ -2882,6 +2896,23 @@ void World::InitRandomBGResetTime() sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset)); } +void World::InitCalendarOldEventsDeletionTime() +{ + time_t now = time(nullptr); + time_t currentDeletionTime = getWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME); + time_t nextDeletionTime = currentDeletionTime ? currentDeletionTime : GetNextTimeWithDayAndHour(-1, getIntConfig(CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR)); + + // If the reset time saved in the worldstate is before now it means the server was offline when the reset was supposed to occur. + // In this case we set the reset time in the past and next world update will do the reset and schedule next one in the future. + if (currentDeletionTime < now) + m_NextCalendarOldEventsDeletionTime = nextDeletionTime - DAY; + else + m_NextCalendarOldEventsDeletionTime = nextDeletionTime; + + if (!currentDeletionTime) + sWorld->setWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME, uint64(m_NextCalendarOldEventsDeletionTime)); +} + void World::InitGuildResetTime() { time_t wstime = time_t(getWorldState(WS_GUILD_DAILY_RESET_TIME)); @@ -2984,6 +3015,15 @@ void World::ResetRandomBG() sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset)); } +void World::CalendarDeleteOldEvents() +{ + sLog->outString("Calendar deletion of old events."); + + m_NextCalendarOldEventsDeletionTime = time_t(m_NextCalendarOldEventsDeletionTime + DAY); + sWorld->setWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME, uint64(m_NextCalendarOldEventsDeletionTime)); + sCalendarMgr->DeleteOldEvents(); +} + void World::ResetGuildCap() { sLog->outString("Guild Daily Cap reset."); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 3fb6180c6..fc48301e7 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -316,6 +316,7 @@ enum WorldIntConfigs CONFIG_GUILD_BANK_EVENT_LOG_COUNT, CONFIG_MIN_LEVEL_STAT_SAVE, CONFIG_RANDOM_BG_RESET_HOUR, + CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR, CONFIG_GUILD_RESET_HOUR, CONFIG_CHARDELETE_KEEP_DAYS, CONFIG_CHARDELETE_METHOD, @@ -493,13 +494,14 @@ enum RealmZone enum WorldStates { - WS_ARENA_DISTRIBUTION_TIME = 20001, // Next arena distribution time - WS_WEEKLY_QUEST_RESET_TIME = 20002, // Next weekly reset time - WS_BG_DAILY_RESET_TIME = 20003, // Next daily BG reset time - WS_CLEANING_FLAGS = 20004, // Cleaning Flags - WS_DAILY_QUEST_RESET_TIME = 20005, // Next daily reset time - WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time - WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly reset time + WS_ARENA_DISTRIBUTION_TIME = 20001, // Next arena distribution time + WS_WEEKLY_QUEST_RESET_TIME = 20002, // Next weekly reset time + WS_BG_DAILY_RESET_TIME = 20003, // Next daily BG reset time + WS_CLEANING_FLAGS = 20004, // Cleaning Flags + WS_DAILY_QUEST_RESET_TIME = 20005, // Next daily reset time + WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time + WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly reset time + WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20008 // Next daily calendar deletions of old events time }; /// Storage class for commands issued for delayed execution @@ -812,11 +814,13 @@ class World void InitWeeklyQuestResetTime(); void InitMonthlyQuestResetTime(); void InitRandomBGResetTime(); + void InitCalendarOldEventsDeletionTime(); void InitGuildResetTime(); void ResetDailyQuests(); void ResetWeeklyQuests(); void ResetMonthlyQuests(); void ResetRandomBG(); + void CalendarDeleteOldEvents(); void ResetGuildCap(); private: static ACE_Atomic_Op m_stopEvent; @@ -879,6 +883,7 @@ class World time_t m_NextWeeklyQuestReset; time_t m_NextMonthlyQuestReset; time_t m_NextRandomBGReset; + time_t m_NextCalendarOldEventsDeletionTime; time_t m_NextGuildReset; //Player Queue diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 352ce24f5..ded2d5d0e 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1338,6 +1338,14 @@ Quests.IgnoreAutoAccept = 0 Quests.IgnoreAutoComplete = 0 +# +# Calendar.DeleteOldEventsHour +# Description: Hour of the day when the daily deletion of old calendar events occurs. +# Range: 0-23 +# Default: 6 - (06:00 AM) + +Calendar.DeleteOldEventsHour = 6 + # # Guild.EventLogRecordsCount # Description: Number of log entries for guild events that are stored per guild. Old entries