server/src/game/CalendarHandler.cpp

1044 lines
40 KiB
C++

/*
* This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; 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
*/
#include "Common.h"
#include "Log.h"
#include "Player.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "MapPersistentStateMgr.h"
#include "Calendar.h"
#include "ObjectMgr.h"
#include "SocialMgr.h"
#include "World.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "ArenaTeam.h"
void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recv_data*/)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_GET_CALENDAR [%s]", guid.GetString().c_str());
time_t currTime = time(NULL);
WorldPacket data(SMSG_CALENDAR_SEND_CALENDAR);
CalendarInvitesList invites;
sCalendarMgr.GetPlayerInvitesList(guid, invites);
data << uint32(invites.size());
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Sending > %u invites", invites.size());
for (CalendarInvitesList::const_iterator itr = invites.begin(); itr != invites.end(); ++itr)
{
CalendarEvent const* event = (*itr)->GetCalendarEvent();
MANGOS_ASSERT(event); // TODO: be sure no way to have a null event
data << uint64(event->EventId);
data << uint64((*itr)->InviteId);
data << uint8((*itr)->Status);
data << uint8((*itr)->Rank);
data << uint8(event->IsGuildEvent());
data << event->CreatorGuid.WriteAsPacked();
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "invite> EventId[" UI64FMTD "], InviteId[" UI64FMTD "], status[%u], rank[%u]",
event->EventId, (*itr)->InviteId, uint32((*itr)->Status), uint32((*itr)->Rank));
}
CalendarEventsList events;
sCalendarMgr.GetPlayerEventsList(guid, events);
data << uint32(events.size());
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Sending > %u events", events.size());
for (CalendarEventsList::const_iterator itr = events.begin(); itr != events.end(); ++itr)
{
CalendarEvent const* event = *itr;
data << uint64(event->EventId);
data << event->Title;
data << uint32(event->Type);
data << secsToTimeBitFields(event->EventTime);
data << uint32(event->Flags);
data << int32(event->DungeonId);
data << event->CreatorGuid.WriteAsPacked();
std::string timeStr = TimeToTimestampStr(event->EventTime);
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Events> EventId[" UI64FMTD "], Title[%s], Time[%s], Type[%u], Flag[%u], DungeonId[%d], CreatorGuid[%s]",
event->EventId, event->Title.c_str(), timeStr.c_str(), uint32(event->Type),
uint32(event->Flags), event->DungeonId, event->CreatorGuid.GetString().c_str());
}
data << uint32(currTime); // server time
data << secsToTimeBitFields(currTime); // zone time ??
ByteBuffer dataBuffer;
uint32 boundCounter = 0;
for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
Player::BoundInstancesMap boundInstances = _player->GetBoundInstances(Difficulty(i));
for (Player::BoundInstancesMap::const_iterator itr = boundInstances.begin(); itr != boundInstances.end(); ++itr)
{
if (itr->second.perm)
{
DungeonPersistentState const* state = itr->second.state;
dataBuffer << uint32(state->GetMapId());
dataBuffer << uint32(state->GetDifficulty());
dataBuffer << uint32(state->GetResetTime() - currTime);
dataBuffer << uint64(state->GetInstanceId()); // instance save id as unique instance copy id
++boundCounter;
}
}
}
data << uint32(boundCounter);
data.append(dataBuffer);
data << uint32(1135753200); // Constant date, unk (28.12.2005 07:00)
// Reuse variables
boundCounter = 0;
std::set<uint32> sentMaps;
dataBuffer.clear();
for (MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr)
{
uint32 map_diff_pair = itr->first;
uint32 mapId = PAIR32_LOPART(map_diff_pair);
Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair));
MapDifficultyEntry const* mapDiff = itr->second;
// skip mapDiff without global reset time
if (!mapDiff->resetTime)
continue;
// skip non raid map
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
if (!mapEntry || !mapEntry->IsRaid())
continue;
// skip already sent map (not same difficulty?)
if (sentMaps.find(mapId) != sentMaps.end())
continue;
uint32 resetTime = sMapPersistentStateMgr.GetScheduler().GetMaxResetTimeFor(mapDiff);
sentMaps.insert(mapId);
dataBuffer << mapId;
dataBuffer << resetTime;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "MapId [%u] -> Reset Time: %u", mapId, resetTime);
dataBuffer << int32(0); // showed 68400 on map 509 must investigate more
++boundCounter;
}
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Map sent [%u]", boundCounter);
data << uint32(boundCounter);
data.append(dataBuffer);
// TODO: Fix this, how we do know how many and what holidays to send?
uint32 holidayCount = 0;
data << uint32(holidayCount);
/*for (uint32 i = 0; i < holidayCount; ++i)
{
HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(666);
data << uint32(holiday->Id); // m_ID
data << uint32(holiday->Region); // m_region, might be looping
data << uint32(holiday->Looping); // m_looping, might be region
data << uint32(holiday->Priority); // m_priority
data << uint32(holiday->CalendarFilterType); // m_calendarFilterType
for (uint8 j = 0; j < MAX_HOLIDAY_DATES; ++j)
data << uint32(holiday->Date[j]); // 26 * m_date -- WritePackedTime ?
for (uint8 j = 0; j < MAX_HOLIDAY_DURATIONS; ++j)
data << uint32(holiday->Duration[j]); // 10 * m_duration
for (uint8 j = 0; j < MAX_HOLIDAY_FLAGS; ++j)
data << uint32(holiday->CalendarFlags[j]); // 10 * m_calendarFlags
data << holiday->TextureFilename; // m_textureFilename (holiday name)
}*/
SendPacket(&data);
}
void WorldSession::HandleCalendarGetEvent(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_GET_EVENT [%s]", guid.GetString().c_str());
uint64 eventId;
recv_data >> eventId;
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
sCalendarMgr.SendCalendarEvent(_player, event, CALENDAR_SENDTYPE_GET);
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarGuildFilter(WorldPacket& recv_data)
{
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_GUILD_FILTER [%s]", _player->GetGuidStr().c_str());
uint32 minLevel;
uint32 maxLevel;
uint32 minRank;
recv_data >> minLevel >> maxLevel >> minRank;
if (Guild* guild = sGuildMgr.GetGuildById(_player->GetGuildId()))
guild->MassInviteToEvent(this, minLevel, maxLevel, minRank);
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Min level [%u], Max level [%u], Min rank [%u]", minLevel, maxLevel, minRank);
}
void WorldSession::HandleCalendarEventSignup(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_EVENT_SIGNUP [%s]", guid.GetString().c_str());
uint64 eventId;
bool tentative;
recv_data >> eventId;
recv_data >> tentative; // uint8 == bool size in all compilator???
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "] Tentative %u", eventId, uint32(tentative));
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
{
if (event->IsGuildEvent() && event->GuildId != _player->GetGuildId())
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_GUILD_PLAYER_NOT_IN_GUILD);
return;
}
CalendarInviteStatus status = tentative ? CALENDAR_STATUS_TENTATIVE : CALENDAR_STATUS_SIGNED_UP;
sCalendarMgr.AddInvite(event, guid, guid, CalendarInviteStatus(status), CALENDAR_RANK_PLAYER, "", time(NULL));
sCalendarMgr.SendCalendarClearPendingAction(_player);
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarArenaTeam(WorldPacket& recv_data)
{
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_ARENA_TEAM [%s]", _player->GetGuidStr().c_str());
uint32 areanTeamId;
recv_data >> areanTeamId;
if (ArenaTeam* team = sObjectMgr.GetArenaTeamById(areanTeamId))
team->MassInviteToEvent(this);
}
void WorldSession::HandleCalendarAddEvent(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_ADD_EVENT [%s]", guid.GetString().c_str());
std::string title;
std::string description;
uint8 type;
uint8 repeatable;
uint32 maxInvites;
int32 dungeonId;
uint32 eventPackedTime;
uint32 unkPackedTime;
uint32 flags;
recv_data >> title;
recv_data >> description;
recv_data >> type;
recv_data >> repeatable;
recv_data >> maxInvites;
recv_data >> dungeonId;
recv_data >> eventPackedTime;
recv_data >> unkPackedTime;
recv_data >> flags;
// 946684800 is 01/01/2000 00:00:00 - default response time
CalendarEvent* cal = sCalendarMgr.AddEvent(_player->GetObjectGuid(), title, description, type, repeatable, maxInvites, dungeonId, timeBitFieldsToSecs(eventPackedTime), timeBitFieldsToSecs(unkPackedTime), flags);
if (cal)
{
if (cal->IsGuildAnnouncement())
{
sCalendarMgr.AddInvite(cal, guid, ObjectGuid(uint64(0)), CALENDAR_STATUS_NOT_SIGNED_UP, CALENDAR_RANK_PLAYER, "", time(NULL));
}
else
{
uint32 inviteCount;
recv_data >> inviteCount;
for (uint32 i = 0; i < inviteCount; ++i)
{
ObjectGuid invitee;
uint8 status = 0;
uint8 rank = 0;
recv_data >> invitee.ReadAsPacked();
recv_data >> status;
recv_data >> rank;
sCalendarMgr.AddInvite(cal, guid, invitee, CalendarInviteStatus(status), CalendarModerationRank(rank), "", time(NULL));
}
}
sCalendarMgr.SendCalendarEvent(_player, cal, CALENDAR_SENDTYPE_ADD);
}
}
void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_UPDATE_EVENT [%s]", guid.GetString().c_str());
time_t oldEventTime;
uint64 eventId;
uint64 inviteId;
std::string title;
std::string description;
uint8 type;
uint8 repetitionType;
uint32 maxInvites;
int32 dungeonId;
uint32 eventPackedTime;
uint32 UnknownPackedTime;
uint32 flags;
recv_data >> eventId >> inviteId >> title >> description >> type >> repetitionType >> maxInvites >> dungeonId;
recv_data >> eventPackedTime;
recv_data >> UnknownPackedTime;
recv_data >> flags;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "], InviteId [" UI64FMTD "] Title %s, Description %s, type %u "
"Repeatable %u, MaxInvites %u, Dungeon ID %d, Flags %u", eventId, inviteId, title.c_str(),
description.c_str(), uint32(type), uint32(repetitionType), maxInvites, dungeonId, flags);
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
{
if (guid != event->CreatorGuid)
{
CalendarInvite* updaterInvite = event->GetInviteByGuid(guid);
if (updaterInvite == NULL)
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NOT_INVITED);
return ;
}
if (updaterInvite->Rank != CALENDAR_RANK_MODERATOR)
{
// remover have not enough right to change invite status
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_PERMISSIONS);
return;
}
}
oldEventTime = event->EventTime;
event->Type = CalendarEventType(type);
event->Flags = flags;
event->EventTime = timeBitFieldsToSecs(eventPackedTime);
event->UnknownTime = timeBitFieldsToSecs(UnknownPackedTime);
event->DungeonId = dungeonId;
event->Title = title;
event->Description = description;
sCalendarMgr.SendCalendarEventUpdateAlert(event, oldEventTime);
// query construction
CharacterDatabase.escape_string(title);
CharacterDatabase.escape_string(description);
CharacterDatabase.PExecute("UPDATE calendar_events SET "
"type=%hu, flags=%u, dungeonId=%d, eventTime=%u, title='%s', description='%s'"
"WHERE eventid=" UI64FMTD,
type, flags, dungeonId, event->EventTime, title.c_str(), description.c_str(), eventId);
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarRemoveEvent(WorldPacket& recv_data)
{
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_REMOVE_EVENT [%s]", _player->GetGuidStr().c_str());
uint64 eventId;
uint64 inviteId;
uint32 Flags;
recv_data >> eventId;
recv_data >> inviteId;
recv_data >> Flags;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Remove event (eventId=" UI64FMTD ", remover inviteId =" UI64FMTD ")", eventId, inviteId);
sCalendarMgr.RemoveEvent(eventId, _player);
}
void WorldSession::HandleCalendarCopyEvent(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_COPY_EVENT [%s]", guid.GetString().c_str());
uint64 eventId;
uint64 inviteId;
uint32 packedTime;
recv_data >> eventId >> inviteId;
recv_data >> packedTime;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "] inviteId [" UI64FMTD "]",
eventId, inviteId);
sCalendarMgr.CopyEvent(eventId, timeBitFieldsToSecs(packedTime), guid);
}
void WorldSession::HandleCalendarEventInvite(WorldPacket& recv_data)
{
ObjectGuid playerGuid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_EVENT_INVITE [%s]", playerGuid.GetString().c_str());
uint64 eventId;
// TODO it seem its not inviteID but event->CreatorGuid
uint64 inviteId;
std::string name;
bool isPreInvite;
bool isGuildEvent;
ObjectGuid inviteeGuid;
uint32 inviteeTeam = 0;
uint32 inviteeGuildId = 0;
bool isIgnored = false;
recv_data >> eventId >> inviteId >> name >> isPreInvite >> isGuildEvent;
if (Player* player = sObjectAccessor.FindPlayerByName(name.c_str()))
{
// Invitee is online
inviteeGuid = player->GetObjectGuid();
inviteeTeam = player->GetTeam();
inviteeGuildId = player->GetGuildId();
if (player->GetSocial()->HasIgnore(playerGuid))
isIgnored = true;
}
else
{
// Invitee offline, get data from database
CharacterDatabase.escape_string(name);
QueryResult* result = CharacterDatabase.PQuery("SELECT guid,race FROM characters WHERE name ='%s'", name.c_str());
if (result)
{
Field* fields = result->Fetch();
inviteeGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32());
inviteeTeam = Player::TeamForRace(fields[1].GetUInt8());
inviteeGuildId = Player::GetGuildIdFromDB(inviteeGuid);
delete result;
result = CharacterDatabase.PQuery("SELECT flags FROM character_social WHERE guid = %u AND friend = %u", inviteeGuid.GetCounter(), playerGuid.GetCounter());
if (result)
{
Field* fields = result->Fetch();
if (fields[0].GetUInt8() & SOCIAL_FLAG_IGNORED)
isIgnored = true;
delete result;
}
}
}
if (inviteeGuid.IsEmpty())
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_PLAYER_NOT_FOUND);
return;
}
if (isIgnored)
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_IGNORING_YOU_S, name.c_str());
return;
}
if (_player->GetTeam() != inviteeTeam && !sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CALENDAR))
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NOT_ALLIED);
return;
}
if (!isPreInvite)
{
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
{
if (event->IsGuildEvent() && event->GuildId == inviteeGuildId)
{
// we can't invite guild members to guild events
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NO_GUILD_INVITES);
return;
}
sCalendarMgr.AddInvite(event, playerGuid, inviteeGuid, CALENDAR_STATUS_INVITED, CALENDAR_RANK_PLAYER, "", time(NULL));
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
else
{
if (isGuildEvent && inviteeGuildId == _player->GetGuildId())
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NO_GUILD_INVITES);
return;
}
// create a temp invite to send it back to client
CalendarInvite invite;
invite.SenderGuid = playerGuid;
invite.InviteeGuid = inviteeGuid;
invite.Status = CALENDAR_STATUS_INVITED;
invite.Rank = CALENDAR_RANK_PLAYER;
invite.LastUpdateTime = time(NULL);
sCalendarMgr.SendCalendarEventInvite(&invite);
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "PREINVITE> sender[%s], Invitee[%u]", playerGuid.GetString().c_str(), inviteeGuid.GetString().c_str());
}
}
void WorldSession::HandleCalendarEventRsvp(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_EVENT_RSVP [%s]", guid.GetString().c_str());
uint64 eventId;
uint64 inviteId;
uint32 status;
recv_data >> eventId >> inviteId >> status;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "], InviteId [" UI64FMTD "], status %u",
eventId, inviteId, status);
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
{
// i think we still should be able to remove self from locked events
if (status != CALENDAR_STATUS_REMOVED && event->Flags & CALENDAR_FLAG_INVITES_LOCKED)
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_LOCKED);
return;
}
if (CalendarInvite* invite = event->GetInviteById(inviteId))
{
if (invite->InviteeGuid != guid)
{
CalendarInvite* updaterInvite = event->GetInviteByGuid(guid);
if (updaterInvite == NULL)
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NOT_INVITED);
return ;
}
if (updaterInvite->Rank != CALENDAR_RANK_MODERATOR && updaterInvite->Rank != CALENDAR_RANK_OWNER)
{
// remover have not enough right to change invite status
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_PERMISSIONS);
return;
}
}
invite->Status = CalendarInviteStatus(status);
invite->LastUpdateTime = time(NULL);
CharacterDatabase.PExecute("UPDATE calendar_invites SET status=%u, lastUpdateTime=%u WHERE inviteId = " UI64FMTD, status, uint32(invite->LastUpdateTime), invite->InviteId);
sCalendarMgr.SendCalendarEventStatus(invite);
sCalendarMgr.SendCalendarClearPendingAction(_player);
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NO_INVITE); // correct?
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_EVENT_REMOVE_INVITE [%s]", guid.GetString().c_str());
ObjectGuid invitee;
uint64 eventId;
uint64 ownerInviteId; // isn't it sender's inviteId? TODO: need more test to see what we can do with that value
uint64 inviteId;
recv_data >> invitee.ReadAsPacked();
recv_data >> inviteId >> ownerInviteId >> eventId;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "], ownerInviteId [" UI64FMTD "], Invitee ([%s] id: [" UI64FMTD "])",
eventId, ownerInviteId, invitee.GetString().c_str(), inviteId);
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
sCalendarMgr.RemoveInvite(eventId, inviteId, guid);
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarEventStatus(WorldPacket& recv_data)
{
ObjectGuid updaterGuid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_EVENT_STATUS [%s]", updaterGuid.GetString().c_str());
recv_data.hexlike();
ObjectGuid invitee;
uint64 eventId;
uint64 inviteId;
uint64 ownerInviteId; // isn't it sender's inviteId?
uint32 status;
recv_data >> invitee.ReadAsPacked();
recv_data >> eventId >> inviteId >> ownerInviteId >> status;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "] ownerInviteId [" UI64FMTD "], Invitee ([%s] id: [" UI64FMTD "], status %u",
eventId, ownerInviteId, invitee.GetString().c_str(), inviteId, status);
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
{
if (CalendarInvite* invite = event->GetInviteById(inviteId))
{
if (invite->InviteeGuid != updaterGuid)
{
CalendarInvite* updaterInvite = event->GetInviteByGuid(updaterGuid);
if (updaterInvite == NULL)
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NOT_INVITED);
return ;
}
if (updaterInvite->Rank != CALENDAR_RANK_MODERATOR && updaterInvite->Rank != CALENDAR_RANK_OWNER)
{
// remover have not enough right to change invite status
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_PERMISSIONS);
return;
}
}
invite->Status = (CalendarInviteStatus)status;
invite->LastUpdateTime = time(NULL); // not sure if we should set response time when moderator changes invite status
CharacterDatabase.PExecute("UPDATE calendar_invites SET status=%u, lastUpdateTime=%u WHERE inviteId=" UI64FMTD, status, uint32(invite->LastUpdateTime), invite->InviteId);
sCalendarMgr.SendCalendarEventStatus(invite);
sCalendarMgr.SendCalendarClearPendingAction(sObjectMgr.GetPlayer(invitee));
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NO_INVITE);
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_EVENT_MODERATOR_STATUS [%s]", guid.GetString().c_str());
ObjectGuid invitee;
uint64 eventId;
uint64 inviteId;
uint64 ownerInviteId; // isn't it sender's inviteId?
uint32 rank;
recv_data >> invitee.ReadAsPacked();
recv_data >> eventId >> inviteId >> ownerInviteId >> rank;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "] ownerInviteId [" UI64FMTD "], Invitee ([%s] id: [" UI64FMTD "], rank %u",
eventId, ownerInviteId, invitee.GetString().c_str(), inviteId, rank);
if (CalendarEvent* event = sCalendarMgr.GetEventById(eventId))
{
if (CalendarInvite* invite = event->GetInviteById(inviteId))
{
if (invite->InviteeGuid != guid)
{
CalendarInvite* updaterInvite = event->GetInviteByGuid(guid);
if (updaterInvite == NULL)
{
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NOT_INVITED);
return ;
}
if (updaterInvite->Rank != CALENDAR_RANK_MODERATOR && updaterInvite->Rank != CALENDAR_RANK_OWNER)
{
// remover have not enough right to change invite status
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_PERMISSIONS);
return;
}
}
if (CalendarModerationRank(rank) == CALENDAR_RANK_OWNER)
{
// cannot set owner
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_PERMISSIONS);
return;
}
CharacterDatabase.PExecute("UPDATE calendar_invites SET rank = %u WHERE inviteId=" UI64FMTD, rank, invite->InviteId);
invite->Rank = CalendarModerationRank(rank);
sCalendarMgr.SendCalendarEventModeratorStatusAlert(invite);
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_NO_INVITE);
}
else
sCalendarMgr.SendCalendarCommandResult(_player, CALENDAR_ERROR_EVENT_INVALID);
}
void WorldSession::HandleCalendarComplain(WorldPacket& recv_data)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_COMPLAIN [%s]", guid.GetString().c_str());
ObjectGuid badGuyGuid;
uint64 eventId;
uint64 inviteId;
recv_data >> badGuyGuid;
recv_data >> eventId >> inviteId;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "EventId [" UI64FMTD "], BadGuyGuid ([%s] inviteId: [" UI64FMTD "])",
eventId, badGuyGuid.GetString().c_str(), inviteId);
// Remove the invite
if (sCalendarMgr.RemoveInvite(eventId, inviteId, guid))
{
WorldPacket data(SMSG_COMPLAIN_RESULT, 1 + 1);
data << uint8(0);
data << uint8(0); // show complain saved. We can send 0x0C to show windows with ok button
SendPacket(&data);
}
}
void WorldSession::HandleCalendarGetNumPending(WorldPacket& /*recv_data*/)
{
ObjectGuid guid = _player->GetObjectGuid();
DEBUG_LOG("WORLD: Received opcode CMSG_CALENDAR_GET_NUM_PENDING [%s]", guid.GetString().c_str());
uint32 pending = sCalendarMgr.GetPlayerNumPending(guid);
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Pending: %u", pending);
WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4);
data << uint32(pending);
SendPacket(&data);
}
//////////////////////////////////////////////////////////////////////////
// Send function
//////////////////////////////////////////////////////////////////////////
void CalendarMgr::SendCalendarEventInviteAlert(CalendarInvite const* invite)
{
DEBUG_LOG("WORLD: SMSG_CALENDAR_EVENT_INVITE_ALERT");
CalendarEvent const* event = invite->GetCalendarEvent();
if (!event)
return;
WorldPacket data(SMSG_CALENDAR_EVENT_INVITE_ALERT);
data << uint64(event->EventId);
data << event->Title;
data << secsToTimeBitFields(event->EventTime);
data << uint32(event->Flags);
data << uint32(event->Type);
data << int32(event->DungeonId);
data << uint64(invite->InviteId);
data << uint8(invite->Status);
data << uint8(invite->Rank);
data << event->CreatorGuid.WriteAsPacked();
data << invite->SenderGuid.WriteAsPacked();
//data.hexlike();
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SendCalendarInviteAlert> senderGuid[%s], inviteeGuid[%s], EventId[" UI64FMTD "], Status[%u], InviteId[" UI64FMTD "]",
invite->SenderGuid.GetString().c_str(), invite->InviteeGuid.GetString().c_str(), event->EventId, uint32(invite->Status), invite->InviteId);
if (event->IsGuildEvent() || event->IsGuildAnnouncement())
{
if (Guild* guild = sGuildMgr.GetGuildById(event->GuildId))
guild->BroadcastPacket(&data);
}
else if (Player* player = sObjectMgr.GetPlayer(invite->InviteeGuid))
player->SendDirectMessage(&data);
}
void CalendarMgr::SendCalendarEventInvite(CalendarInvite const* invite)
{
CalendarEvent const* event = invite->GetCalendarEvent();
time_t statusTime = invite->LastUpdateTime;
bool preInvite = true;
uint64 eventId = 0;
if (event != NULL)
{
preInvite = false;
eventId = event->EventId;
}
Player* player = sObjectMgr.GetPlayer(invite->InviteeGuid);
uint8 level = player ? player->getLevel() : Player::GetLevelFromDB(invite->InviteeGuid);
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_INVITE");
WorldPacket data(SMSG_CALENDAR_EVENT_INVITE, 8 + 8 + 8 + 1 + 1 + 1 + (preInvite ? 0 : 4) + 1);
data << invite->InviteeGuid.WriteAsPacked();
data << uint64(eventId);
data << uint64(invite->InviteId);
data << uint8(level);
data << uint8(invite->Status);
data << uint8(!preInvite);
if (!preInvite)
data << secsToTimeBitFields(statusTime);
data << uint8(invite->SenderGuid != invite->InviteeGuid); // false only if the invite is sign-up (invitee create himself his invite)
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SendCalendarInvit> %s senderGuid[%s], inviteeGuid[%s], EventId[" UI64FMTD "], Status[%u], InviteId[" UI64FMTD "]",
preInvite ? "is PreInvite," : "", invite->SenderGuid.GetString().c_str(), invite->InviteeGuid.GetString().c_str(), eventId, uint32(invite->Status), invite->InviteId);
//data.hexlike();
if (preInvite)
{
if (Player* sender = sObjectMgr.GetPlayer(invite->SenderGuid))
sender->SendDirectMessage(&data);
}
else
SendPacketToAllEventRelatives(data, event);
}
void CalendarMgr::SendCalendarCommandResult(Player* player, CalendarError err, char const* param /*= NULL*/)
{
if (!player)
return;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_COMMAND_RESULT (%u)", err);
WorldPacket data(SMSG_CALENDAR_COMMAND_RESULT, 0);
data << uint32(0);
data << uint8(0);
switch (err)
{
case CALENDAR_ERROR_OTHER_INVITES_EXCEEDED_S:
case CALENDAR_ERROR_ALREADY_INVITED_TO_EVENT_S:
case CALENDAR_ERROR_IGNORING_YOU_S:
data << param;
break;
default:
data << uint8(0);
break;
}
data << uint32(err);
//data.hexlike();
player->SendDirectMessage(&data);
}
void CalendarMgr::SendCalendarEventRemovedAlert(CalendarEvent const* event)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_REMOVED_ALERT");
WorldPacket data(SMSG_CALENDAR_EVENT_REMOVED_ALERT, 1 + 8 + 1);
data << uint8(1); // show pending alert?
data << uint64(event->EventId);
data << secsToTimeBitFields(event->EventTime);
//data.hexlike();
SendPacketToAllEventRelatives(data, event);
}
void CalendarMgr::SendCalendarEvent(Player* player, CalendarEvent const* event, uint32 sendType)
{
if (!player || !event)
return;
std::string timeStr = TimeToTimestampStr(event->EventTime);
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SendCalendarEvent> sendType[%u], CreatorGuid[%s], EventId[" UI64FMTD "], Type[%u], Flags[%u], Title[%s]",
sendType, event->CreatorGuid.GetString().c_str(), event->EventId, uint32(event->Type), event->Flags, event->Title.c_str());
WorldPacket data(SMSG_CALENDAR_SEND_EVENT);
data << uint8(sendType);
data << event->CreatorGuid.WriteAsPacked();
data << uint64(event->EventId);
data << event->Title;
data << event->Description;
data << uint8(event->Type);
data << uint8(event->Repeatable);
data << uint32(CALENDAR_MAX_INVITES);
data << event->DungeonId;
data << event->Flags;
data << secsToTimeBitFields(event->EventTime);
data << secsToTimeBitFields(event->UnknownTime);
data << event->GuildId;
CalendarInviteMap const* cInvMap = event->GetInviteMap();
data << (uint32)cInvMap->size();
for (CalendarInviteMap::const_iterator itr = cInvMap->begin(); itr != cInvMap->end(); ++itr)
{
CalendarInvite const* invite = itr->second;
ObjectGuid inviteeGuid = invite->InviteeGuid;
Player* invitee = sObjectMgr.GetPlayer(inviteeGuid);
uint8 inviteeLevel = invitee ? invitee->getLevel() : Player::GetLevelFromDB(inviteeGuid);
uint32 inviteeGuildId = invitee ? invitee->GetGuildId() : Player::GetGuildIdFromDB(inviteeGuid);
data << inviteeGuid.WriteAsPacked();
data << uint8(inviteeLevel);
data << uint8(invite->Status);
data << uint8(invite->Rank);
data << uint8(event->IsGuildEvent() && event->GuildId == inviteeGuildId);
data << uint64(itr->first);
data << secsToTimeBitFields(invite->LastUpdateTime);
data << invite->Text;
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "Invite> InviteId[" UI64FMTD "], InviteLvl[%u], Status[%u], Rank[%u], GuildEvent[%s], Text[%s]",
invite->InviteId, uint32(inviteeLevel), uint32(invite->Status), uint32(invite->Rank),
(event->IsGuildEvent() && event->GuildId == inviteeGuildId) ? "true" : "false", invite->Text.c_str());
}
//data.hexlike();
player->SendDirectMessage(&data);
}
void CalendarMgr::SendCalendarEventInviteRemove(CalendarInvite const* invite, uint32 flags)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_INVITE_REMOVED");
CalendarEvent const* event = invite->GetCalendarEvent();
WorldPacket data(SMSG_CALENDAR_EVENT_INVITE_REMOVED, 8 + 4 + 4 + 1);
data.appendPackGUID(invite->InviteeGuid);
data << uint64(event->EventId);
data << uint32(flags);
data << uint8(1); // show pending alert?
//data.hexlike();
SendPacketToAllEventRelatives(data, event);
}
void CalendarMgr::SendCalendarEventInviteRemoveAlert(Player* player, CalendarEvent const* event, CalendarInviteStatus status)
{
if (player)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT");
WorldPacket data(SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT, 8 + 4 + 4 + 1);
data << uint64(event->EventId);
data << secsToTimeBitFields(event->EventTime);
data << uint32(event->Flags);
data << uint8(status);
//data.hexlike();
player->SendDirectMessage(&data);
}
}
void CalendarMgr::SendCalendarEventStatus(CalendarInvite const* invite)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_STATUS");
WorldPacket data(SMSG_CALENDAR_EVENT_STATUS, 8 + 8 + 4 + 4 + 1 + 1 + 4);
CalendarEvent const* event = invite->GetCalendarEvent();
data << invite->InviteeGuid.WriteAsPacked();
data << uint64(event->EventId);
data << secsToTimeBitFields(event->EventTime);
data << uint32(event->Flags);
data << uint8(invite->Status);
data << uint8(invite->Rank);
data << secsToTimeBitFields(invite->LastUpdateTime);
//data.hexlike();
SendPacketToAllEventRelatives(data, event);
}
void CalendarMgr::SendCalendarClearPendingAction(Player* player)
{
if (player)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_CLEAR_PENDING_ACTION TO [%s]", player->GetObjectGuid().GetString().c_str());
WorldPacket data(SMSG_CALENDAR_CLEAR_PENDING_ACTION, 0);
player->SendDirectMessage(&data);
}
}
void CalendarMgr::SendCalendarEventModeratorStatusAlert(CalendarInvite const* invite)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT");
CalendarEvent const* event = invite->GetCalendarEvent();
WorldPacket data(SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT, 8 + 8 + 1 + 1);
data << invite->InviteeGuid.WriteAsPacked();
data << uint64(event->EventId);
data << uint8(invite->Rank);
data << uint8(1); // Display pending action to client?
//data.hexlike();
SendPacketToAllEventRelatives(data, event);
}
void CalendarMgr::SendCalendarEventUpdateAlert(CalendarEvent const* event, time_t oldEventTime)
{
DEBUG_FILTER_LOG(LOG_FILTER_CALENDAR, "SMSG_CALENDAR_EVENT_UPDATED_ALERT");
WorldPacket data(SMSG_CALENDAR_EVENT_UPDATED_ALERT, 1 + 8 + 4 + 4 + 4 + 1 + 4 +
event->Title.size() + event->Description.size() + 1 + 4 + 4);
data << uint8(1); // show pending alert?
data << uint64(event->EventId);
data << secsToTimeBitFields(oldEventTime);
data << uint32(event->Flags);
data << secsToTimeBitFields(event->EventTime);
data << uint8(event->Type);
data << int32(event->DungeonId);
data << event->Title;
data << event->Description;
data << uint8(event->Repeatable);
data << uint32(CALENDAR_MAX_INVITES);
data << secsToTimeBitFields(event->UnknownTime);
//data.hexlike();
SendPacketToAllEventRelatives(data, event);
}
void CalendarMgr::SendPacketToAllEventRelatives(WorldPacket packet, CalendarEvent const* event)
{
// Send packet to all guild members
if (event->IsGuildEvent() || event->IsGuildAnnouncement())
if (Guild* guild = sGuildMgr.GetGuildById(event->GuildId))
guild->BroadcastPacket(&packet);
// Send packet to all invitees if event is non-guild, in other case only to non-guild invitees (packet was broadcasted for them)
CalendarInviteMap const* cInvMap = event->GetInviteMap();
for (CalendarInviteMap::const_iterator itr = cInvMap->begin(); itr != cInvMap->end(); ++itr)
if (Player* player = sObjectMgr.GetPlayer(itr->second->InviteeGuid))
if (!event->IsGuildEvent() || (event->IsGuildEvent() && player->GetGuildId() != event->GuildId))
player->SendDirectMessage(&packet);
}
void CalendarMgr::SendCalendarRaidLockoutRemove(Player* player, DungeonPersistentState const* save)
{
if (!save || !player)
return;
DEBUG_LOG("SMSG_CALENDAR_RAID_LOCKOUT_REMOVED [%s]", player->GetObjectGuid().GetString().c_str());
time_t currTime = time(NULL);
WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_REMOVED, 4 + 4 + 4 + 8);
data << uint32(save->GetMapId());
data << uint32(save->GetDifficulty());
data << uint32(save->GetResetTime() - currTime);
data << uint64(save->GetInstanceId());
//data.hexlike();
player->SendDirectMessage(&data);
}
void CalendarMgr::SendCalendarRaidLockoutAdd(Player* player, DungeonPersistentState const* save)
{
if (!save || !player)
return;
DEBUG_LOG("SMSG_CALENDAR_RAID_LOCKOUT_ADDED [%s]", player->GetObjectGuid().GetString().c_str());
time_t currTime = time(NULL);
WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_ADDED, 4 + 4 + 4 + 4 + 8);
data << secsToTimeBitFields(currTime);
data << uint32(save->GetMapId());
data << uint32(save->GetDifficulty());
data << uint32(save->GetResetTime() - currTime);
data << uint64(save->GetInstanceId());
//data.hexlike();
player->SendDirectMessage(&data);
}