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.
This commit is contained in:
Giacomo Pozzoni
2019-09-17 09:11:56 +02:00
committed by GitHub
parent 6fc7ab3448
commit fb059722fd
9 changed files with 238 additions and 39 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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.");

View File

@@ -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

View File

@@ -1045,6 +1045,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