aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGiacomo Pozzoni <giacomopoz@gmail.com>2019-09-17 09:11:56 +0200
committerGitHub <noreply@github.com>2019-09-17 09:11:56 +0200
commitfb059722fdb18a94d47b3f44a5b2d7f183bf5a29 (patch)
treebd492eb60a771dd7fd3f712b1e0a63d4110df45b /src
parent6fc7ab3448850199835f9ee9dca6991b511eba09 (diff)
Core/Calendar: Add some additional validation when creating events (#23797)
* Core/Calendar: Add some additional validation when creating events Allow only 30 player events and 100 guild events to be created. Don't allow to create guild events if player is not in guild. Send some more error messages to the client (not blizzlike errors but better than nothing). * Core/Calendar: Add some additional validation/checks Add guild id check in GetPlayerEvents(). Change error message in HandleCalendarCopyEvent() to be the same as in HandleCalendarAddEvent() when creating an event in the past. * Core/Calendar: Add some additional validation/checks Reduce the number of CMSG_CALENDAR_ADD_EVENT packets a seconds allowed from 10 to 3. * Core/Calendar: Add some additional validation/checks Implement 5 seconds cooldown between the creation of calendar events * Core/Calendar: Add some additional validation/checks Don't allow to copy events of a different player/guild * Core/Calendar: Implement automatic deletion of old events Implement automatic deletion of events older than 1 month (30 days). Fix debug assertion triggered when deleting a character with calendar events. Avoid double std::set lookup when deleting events when deleting a character. NB: The whole CalendarMgr/CalendarHandler code should be checked line by line for bugs/crashes/exploits.
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp72
-rw-r--r--src/server/game/Calendar/CalendarMgr.h19
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp99
-rw-r--r--src/server/game/Server/WorldSession.cpp10
-rw-r--r--src/server/game/Server/WorldSession.h16
-rw-r--r--src/server/game/World/World.cpp44
-rw-r--r--src/server/game/World/World.h7
-rw-r--r--src/server/worldserver/worldserver.conf.dist8
9 files changed, 238 insertions, 39 deletions
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index b16579f0a71..fda4a5f984b 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -175,13 +175,24 @@ void CalendarMgr::RemoveEvent(uint64 eventId, ObjectGuid remover)
return;
}
+ RemoveEvent(calendarEvent, remover);
+}
+
+void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover)
+{
+ if (!calendarEvent)
+ {
+ SendCalendarCommandResult(remover, CALENDAR_ERROR_EVENT_INVALID);
+ return;
+ }
+
SendCalendarEventRemovedAlert(*calendarEvent);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
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];
@@ -197,10 +208,10 @@ void CalendarMgr::RemoveEvent(uint64 eventId, ObjectGuid remover)
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);
@@ -280,9 +291,13 @@ void CalendarMgr::UpdateInvite(CalendarInvite* invite, SQLTransaction& trans)
void CalendarMgr::RemoveAllPlayerEventsAndInvites(ObjectGuid guid)
{
- for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
- if ((*itr)->GetCreatorGUID() == guid)
- RemoveEvent((*itr)->GetEventId(), ObjectGuid::Empty); // don't send mail if removing a character
+ for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end();)
+ {
+ CalendarEvent* event = *itr;
+ ++itr;
+ if (event->GetCreatorGUID() == guid)
+ RemoveEvent(event, ObjectGuid::Empty); // don't send mail if removing a character
+ }
CalendarInviteStore playerInvites = GetPlayerInvites(guid);
for (CalendarInviteStore::const_iterator itr = playerInvites.begin(); itr != playerInvites.end(); ++itr)
@@ -359,6 +374,44 @@ uint64 CalendarMgr::GetFreeInviteId()
return inviteId;
}
+void CalendarMgr::DeleteOldEvents()
+{
+ time_t oldEventsTime = GameTime::GetGameTime() - 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, ObjectGuid::Empty);
+ }
+}
+
+CalendarEventStore CalendarMgr::GetEventsCreatedBy(ObjectGuid 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(ObjectGuid::LowType 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(ObjectGuid guid)
{
CalendarEventStore events;
@@ -370,9 +423,10 @@ CalendarEventStore CalendarMgr::GetPlayerEvents(ObjectGuid guid)
events.insert(event);
if (Player* player = ObjectAccessor::FindConnectedPlayer(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 c762dc10174..e170cdb3151 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -127,9 +127,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 TC_GAME_API CalendarInvite
{
@@ -251,6 +256,9 @@ struct TC_GAME_API CalendarEvent
bool IsGuildEvent() const { return (_flags & CALENDAR_FLAG_GUILD_EVENT) != 0; }
bool IsGuildAnnouncement() const { return (_flags & CALENDAR_FLAG_WITHOUT_INVITES) != 0; }
+ 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(ObjectGuid remover) const;
std::string BuildCalendarMailBody() const;
@@ -291,7 +299,9 @@ class TC_GAME_API CalendarMgr
CalendarEvent* GetEvent(uint64 eventId) const;
CalendarEventStore const& GetEvents() const { return _events; }
+ CalendarEventStore GetEventsCreatedBy(ObjectGuid guid, bool includeGuildEvents = false);
CalendarEventStore GetPlayerEvents(ObjectGuid guid);
+ CalendarEventStore GetGuildEvents(ObjectGuid::LowType guildId);
CalendarInvite* GetInvite(uint64 inviteId) const;
CalendarEventInviteStore const& GetInvites() const { return _invites; }
@@ -303,10 +313,13 @@ class TC_GAME_API CalendarMgr
void FreeInviteId(uint64 id);
uint64 GetFreeInviteId();
+ void DeleteOldEvents();
+
uint32 GetPlayerNumPending(ObjectGuid guid);
void AddEvent(CalendarEvent* calendarEvent, CalendarSendEventType sendType);
void RemoveEvent(uint64 eventId, ObjectGuid remover);
+ void RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover);
void UpdateEvent(CalendarEvent* calendarEvent);
void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite);
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 61c8753bf8a..9dba4371040 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -540,7 +540,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
{
// Create new rolecheck
LfgRoleCheck& roleCheck = RoleChecksStore[gguid];
- roleCheck.cancelTime = time_t(GameTime::GetGameTime()) + LFG_TIME_ROLECHECK;
+ roleCheck.cancelTime = GameTime::GetGameTime() + LFG_TIME_ROLECHECK;
roleCheck.state = LFG_ROLECHECK_INITIALITING;
roleCheck.leader = guid;
roleCheck.dungeons = dungeons;
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index 3ee233a4c76..46839c4b147 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -245,15 +245,54 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
if (time_t(eventPackedTime) < (GameTime::GetGameTime() - 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() > GameTime::GetGameTime())
+ {
+ recvData.rfinish();
+ sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_INTERNAL);
+ return;
+ }
+ SetCalendarEventCreationCooldown(GameTime::GetGameTime() + CALENDAR_CREATE_EVENT_COOLDOWN);
+
CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId,
time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description);
if (calendarEvent->IsGuildEvent() || calendarEvent->IsGuildAnnouncement())
- if (Player* creator = ObjectAccessor::FindPlayer(guid))
- calendarEvent->SetGuildId(creator->GetGuildId());
+ calendarEvent->SetGuildId(_player->GetGuildId());
if (calendarEvent->IsGuildAnnouncement())
{
@@ -266,12 +305,11 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
else
{
// client limits the amount of players to be invited to 100
- const uint32 MaxPlayerInvites = 100;
uint32 inviteCount;
- ObjectGuid invitee[MaxPlayerInvites];
- uint8 status[MaxPlayerInvites];
- uint8 rank[MaxPlayerInvites];
+ ObjectGuid invitee[CALENDAR_MAX_INVITES];
+ uint8 status[CALENDAR_MAX_INVITES];
+ uint8 rank[CALENDAR_MAX_INVITES];
memset(status, 0, sizeof(status));
memset(rank, 0, sizeof(rank));
@@ -280,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 >> invitee[i].ReadAsPacked();
recvData >> status[i] >> rank[i];
@@ -297,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]), "");
@@ -398,12 +436,55 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket& recvData)
// To Do: properly handle timezones and remove the "- time_t(86400L)" hack
if (time_t(eventTime) < (GameTime::GetGameTime() - 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() > GameTime::GetGameTime())
+ {
+ sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_INTERNAL);
+ return;
+ }
+ SetCalendarEventCreationCooldown(GameTime::GetGameTime() + 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 a722e2e0e10..4314e819b86 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -134,13 +134,13 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
m_currentBankerGUID(),
_timeSyncClockDeltaQueue(6),
_timeSyncClockDelta(0),
- _pendingTimeSyncRequests()
+ _pendingTimeSyncRequests(),
+ _timeSyncNextCounter(0),
+ _timeSyncTimer(0),
+ _calendarEventCreationCooldown(0)
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
- _timeSyncNextCounter = 0;
- _timeSyncTimer = 0;
-
if (sock)
{
m_Address = sock->GetRemoteIpAddress().to_string();
@@ -1499,7 +1499,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_GROUP_SET_LEADER: // 1 2 1 async db query
case CMSG_GROUP_RAID_CONVERT: // 1 5 1 async db query
case CMSG_GROUP_ASSISTANT_LEADER: // 1 2 1 async db query
- case CMSG_CALENDAR_ADD_EVENT: // 21 10 2 async db query
case CMSG_PETITION_BUY: // not profiled 1 sync 1 async db queries
case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: // not profiled
case CMSG_REQUEST_VEHICLE_PREV_SEAT: // not profiled
@@ -1522,6 +1521,7 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case CMSG_GMTICKET_UPDATETEXT: // 0 15 1 async db query
case CMSG_GMTICKET_DELETETICKET: // 1 25 1 async db query
case CMSG_GMRESPONSE_RESOLVE: // 1 25 1 async db query
+ case CMSG_CALENDAR_ADD_EVENT: // 21 10 2 async db query
case CMSG_CALENDAR_UPDATE_EVENT: // not profiled
case CMSG_CALENDAR_REMOVE_EVENT: // not profiled
case CMSG_CALENDAR_COPY_EVENT: // not profiled
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index f806fec586c..d7ff80129b0 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -409,8 +409,6 @@ class TC_GAME_API WorldSession
m_TutorialsChanged |= TUTORIALS_FLAG_CHANGED;
}
}
- //used with item_page table
- bool SendItemInfo(uint32 itemid, WorldPacket data);
//auction
void SendAuctionHello(ObjectGuid guid, Creature* unit);
void SendAuctionCommandResult(uint32 auctionItemId, AuctionAction command, AuctionError errorCode, InventoryResult bagResult = InventoryResult(0));
@@ -462,6 +460,10 @@ class TC_GAME_API WorldSession
void ResetTimeSync();
void SendTimeSync();
+ // 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
@@ -498,7 +500,6 @@ class TC_GAME_API WorldSession
// new
void HandleMoveUnRootAck(WorldPacket& recvPacket);
void HandleMoveRootAck(WorldPacket& recvPacket);
- void HandleLookingForGroup(WorldPacket& recvPacket);
// new inspect
void HandleInspectOpcode(WorldPacket& recvPacket);
@@ -526,7 +527,6 @@ class TC_GAME_API WorldSession
void HandleMoveTeleportAck(WorldPacket& recvPacket);
void HandleForceSpeedChangeAck(WorldPacket& recvData);
- void HandlePingOpcode(WorldPacket& recvPacket);
void HandleRepopRequestOpcode(WorldPacket& recvPacket);
void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket);
void HandleLootMoneyOpcode(WorldPacket& recvPacket);
@@ -578,7 +578,6 @@ class TC_GAME_API WorldSession
void HandleSetActionButtonOpcode(WorldPacket& recvPacket);
void HandleGameObjectUseOpcode(WorldPacket& recPacket);
- void HandleMeetingStoneInfo(WorldPacket& recPacket);
void HandleGameobjectReportUse(WorldPacket& recvPacket);
void HandleNameQueryOpcode(WorldPacket& recvPacket);
@@ -603,10 +602,8 @@ class TC_GAME_API WorldSession
void HandleRequestRaidInfoOpcode(WorldPacket& recvData);
void HandleBattlefieldStatusOpcode(WorldPacket& recvData);
- void HandleBattleMasterHelloOpcode(WorldPacket& recvData);
void HandleGroupInviteOpcode(WorldPacket& recvPacket);
- //void HandleGroupCancelOpcode(WorldPacket& recvPacket);
void HandleGroupAcceptOpcode(WorldPacket& recvPacket);
void HandleGroupDeclineOpcode(WorldPacket& recvPacket);
void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
@@ -721,7 +718,6 @@ class TC_GAME_API 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);
@@ -804,7 +800,6 @@ class TC_GAME_API 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);
@@ -1116,6 +1111,9 @@ class TC_GAME_API WorldSession
uint32 _timeSyncNextCounter;
uint32 _timeSyncTimer;
+ // Packets cooldown
+ time_t _calendarEventCreationCooldown;
+
WorldSession(WorldSession const& right) = delete;
WorldSession& operator=(WorldSession const& right) = delete;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index f4c188434c4..6e1958b6a97 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -120,6 +120,7 @@ World::World()
m_NextWeeklyQuestReset = 0;
m_NextMonthlyQuestReset = 0;
m_NextRandomBGReset = 0;
+ m_NextCalendarOldEventsDeletionTime = 0;
m_NextGuildReset = 0;
m_defaultDbcLocale = LOCALE_enUS;
@@ -1132,6 +1133,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)
+ {
+ TC_LOG_ERROR("misc", "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)
{
@@ -2166,6 +2174,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Calculate random battleground reset time...");
InitRandomBGResetTime();
+ TC_LOG_INFO("server.loading", "Calculate deletion of old calendar events time...");
+ InitCalendarOldEventsDeletionTime();
+
TC_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time...");
InitGuildResetTime();
@@ -2313,6 +2324,9 @@ void World::Update(uint32 diff)
if (currentGameTime > m_NextRandomBGReset)
ResetRandomBG();
+ if (currentGameTime > m_NextCalendarOldEventsDeletionTime)
+ CalendarDeleteOldEvents();
+
if (currentGameTime > m_NextGuildReset)
ResetGuildCap();
@@ -3248,7 +3262,7 @@ void World::InitRandomBGResetTime()
{
time_t bgtime = uint64(sWorld->getWorldState(WS_BG_DAILY_RESET_TIME));
if (!bgtime)
- m_NextRandomBGReset = time_t(GameTime::GetGameTime()); // game time not yet init
+ m_NextRandomBGReset = GameTime::GetGameTime(); // game time not yet init
// generate time by config
time_t curTime = GameTime::GetGameTime();
@@ -3272,11 +3286,28 @@ void World::InitRandomBGResetTime()
sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset));
}
+void World::InitCalendarOldEventsDeletionTime()
+{
+ time_t now = GameTime::GetGameTime();
+ time_t nextDeletionTime = GetLocalHourTimestamp(now, getIntConfig(CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR));
+ time_t currentDeletionTime = getWorldState(WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME);
+
+ // 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 gtime = uint64(getWorldState(WS_GUILD_DAILY_RESET_TIME));
if (!gtime)
- m_NextGuildReset = time_t(GameTime::GetGameTime()); // game time not yet init
+ m_NextGuildReset = GameTime::GetGameTime(); // game time not yet init
// generate time by config
time_t curTime = GameTime::GetGameTime();
@@ -3328,6 +3359,15 @@ void World::ResetRandomBG()
sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset));
}
+void World::CalendarDeleteOldEvents()
+{
+ TC_LOG_INFO("misc", "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()
{
TC_LOG_INFO("misc", "Guild Daily Cap reset.");
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 9e144de6da2..28fc6a5f937 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -335,6 +335,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,
@@ -532,7 +533,8 @@ enum WorldStates
WS_CLEANING_FLAGS = 20004, // Cleaning Flags
WS_GUILD_DAILY_RESET_TIME = 20006, // Next guild cap reset time
WS_MONTHLY_QUEST_RESET_TIME = 20007, // Next monthly quest reset time
- WS_DAILY_QUEST_RESET_TIME = 20008 // Next daily quest reset time
+ WS_DAILY_QUEST_RESET_TIME = 20008, // Next daily quest reset time
+ WS_DAILY_CALENDAR_DELETION_OLD_EVENTS_TIME = 20009, // Next daily calendar deletions of old events time
};
/// Storage class for commands issued for delayed execution
@@ -788,8 +790,10 @@ class TC_GAME_API World
void ResetMonthlyQuests();
void InitRandomBGResetTime();
+ void InitCalendarOldEventsDeletionTime();
void InitGuildResetTime();
void ResetRandomBG();
+ void CalendarDeleteOldEvents();
void ResetGuildCap();
private:
World();
@@ -849,6 +853,7 @@ class TC_GAME_API 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 c308bc9d03d..58694ade631 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1046,6 +1046,14 @@ Quests.DailyResetTime = 3
Quests.WeeklyResetWDay = 3
#
+# 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
# will be overwritten if the number of log entries exceed the configured value.