mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 18:36:31 +01:00
- Logging System is asyncronous to improve performance.
- Each msg and Logger has a Log Type and Log Level assigned. Each msg is assigned the Logger of same Log Type or "root" Logger is selected if there is no Logger configured for the given Log Type
- Loggers have a list of Appenders to send the msg to. The Msg in the Logger is not sent to Appenders if the msg LogLevel is lower than Logger LogLevel.
- There are three (at the moment) types of Appenders: Console, File or DB (this is WIP, not working ATM). Msg is not written to the resource if msg LogLevel is lower than Appender LogLevel.
- Appender and Console Log levels can be changed while server is active with command '.set loglevel (a/l) name level'
Explanation of use with Sample config:
Appender.Console.Type=1 (1 = Console)
Appender.Console.Level=2 (2 = Debug)
Appender.Server.Type=2 (2 = File)
Appender.Server.Level=3 (3 = Info)
Appender.Server.File=Server.log
Appender.SQL.Type=2 (2 = File)
Appender.SQL.Level=1 (1 = Trace)
Appender.SQL.File=sql.log
Appenders=Console Server (NOTE: SQL has not been included here... that will make core ignore the config for "SQL" as it's not in this list)
Logger.root.Type=0 (0 = Default - if it's not created by config, server will create it with LogLevel = DISABLED)
Logger.root.Level=5 (5 = Error)
Logger.root.Appenders=Console
Logger.SQL.Type=26 (26 = SQL)
Logger.SQL.Level=3 (2 = Debug)
Logger.SQL.Appenders=Console Server SQL
Logger.SomeRandomName.Type=24 (24 = Guild)
Logger.SomeRandomName.Level=5 (5 = Error)
Loggers=root SQL SomeRandomName
* At loading Appender SQL will be ignored, as it's not present on "Appenders"
* sLog->outDebug(LOG_FILTER_GUILD, "Some log msg related to Guilds")
- Msg is sent to Logger of Type LOG_FILTER_GUILD (24). Logger with name SomeRandomName is found but it's LogLevel = 5 and Msg LogLevel=2... Msg is not logged
* sLog->outError(LOG_FILTER_GUILD, "Some error log msg related to Guilds")
- Msg is sent to Logger of Type LOG_FILTER_GUILD (24). Logger with name SomeRandomeName is found with proper LogLevel but Logger does not have any Appenders assigned to that logger... Msg is not logged
* sLog->outDebug(LOG_FILTER_SQL, "Some msg related to SQLs")
- Msg is sent to Logger SQL (matches type), as it matches LogLevel the msg is sent to Appenders Console, Server and SQL
- Appender Console has lower Log Level: Msg is logged to Console
- Appender Server has higher Log Level: Msg is not logged to file
- Appender SQL has lower Log Level: Msg is logged to file sql.log
* sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Some msg related to Battelgrounds")
- Msg is sent to Logger root (Type 0) as no Logger was found with Type LOG_FILTER_BATTLEGROUND (13). As Logger has higher LogLevel msg is not sent to any appender
* sLog->outError(LOG_FILTER_BATTLEGROUND, "Some error msg related to Battelgrounds")
- Msg is sent to Logger root (Type 0) as no Logger was found with Type LOG_FILTER_BATTLEGROUND (13). Msg has lower LogLevel and is sent to Appender Console
- Appender Console has lower LogLevel: Msg is logged to Console
992 lines
30 KiB
C++
Executable File
992 lines
30 KiB
C++
Executable File
/*
|
|
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "Common.h"
|
|
#include "DatabaseEnv.h"
|
|
#include "Opcodes.h"
|
|
#include "Log.h"
|
|
#include "WorldPacket.h"
|
|
#include "WorldSession.h"
|
|
#include "World.h"
|
|
#include "ObjectMgr.h"
|
|
#include "GroupMgr.h"
|
|
#include "Player.h"
|
|
#include "Group.h"
|
|
#include "SocialMgr.h"
|
|
#include "Util.h"
|
|
#include "SpellAuras.h"
|
|
#include "Vehicle.h"
|
|
|
|
class Aura;
|
|
|
|
/* differeces from off:
|
|
-you can uninvite yourself - is is useful
|
|
-you can accept invitation even if leader went offline
|
|
*/
|
|
/* todo:
|
|
-group_destroyed msg is sent but not shown
|
|
-reduce xp gaining when in raid group
|
|
-quest sharing has to be corrected
|
|
-FIX sending PartyMemberStats
|
|
*/
|
|
|
|
void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val /* = 0 */)
|
|
{
|
|
WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4);
|
|
data << uint32(operation);
|
|
data << member;
|
|
data << uint32(res);
|
|
data << uint32(val); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S)
|
|
|
|
SendPacket(&data);
|
|
}
|
|
|
|
void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE");
|
|
|
|
std::string membername;
|
|
recv_data >> membername;
|
|
recv_data.read_skip<uint32>();
|
|
|
|
// attempt add selected player
|
|
|
|
// cheating
|
|
if (!normalizePlayerName(membername))
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
|
|
return;
|
|
}
|
|
|
|
Player* player = sObjectAccessor->FindPlayerByName(membername.c_str());
|
|
|
|
// no player
|
|
if (!player)
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
|
|
return;
|
|
}
|
|
|
|
// restrict invite to GMs
|
|
if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
|
|
return;
|
|
}
|
|
|
|
// can't group with
|
|
if (!GetPlayer()->isGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION);
|
|
return;
|
|
}
|
|
if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S);
|
|
return;
|
|
}
|
|
// just ignore us
|
|
if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
|
|
return;
|
|
}
|
|
|
|
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
|
|
return;
|
|
}
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (group && group->isBGGroup())
|
|
group = GetPlayer()->GetOriginalGroup();
|
|
|
|
Group* group2 = player->GetGroup();
|
|
if (group2 && group2->isBGGroup())
|
|
group2 = player->GetOriginalGroup();
|
|
// player already in another group or invited
|
|
if (group2 || player->GetGroupInvite())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S);
|
|
|
|
if (group2)
|
|
{
|
|
// tell the player that they were invited but it failed as they were already in a group
|
|
WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
|
|
data << uint8(0); // invited/already in group flag
|
|
data << GetPlayer()->GetName(); // max len 48
|
|
data << uint32(0); // unk
|
|
data << uint8(0); // count
|
|
data << uint32(0); // unk
|
|
player->GetSession()->SendPacket(&data);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (group)
|
|
{
|
|
// not have permissions for invite
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER);
|
|
return;
|
|
}
|
|
// not have place
|
|
if (group->IsFull())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ok, but group not exist, start a new group
|
|
// but don't create and save the group to the DB until
|
|
// at least one person joins
|
|
if (!group)
|
|
{
|
|
group = new Group;
|
|
// new group: if can't add then delete
|
|
if (!group->AddLeaderInvite(GetPlayer()))
|
|
{
|
|
delete group;
|
|
return;
|
|
}
|
|
if (!group->AddInvite(player))
|
|
{
|
|
delete group;
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// already existed group: if can't add then just leave
|
|
if (!group->AddInvite(player))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ok, we do it
|
|
WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
|
|
data << uint8(1); // invited/already in group flag
|
|
data << GetPlayer()->GetName(); // max len 48
|
|
data << uint32(0); // unk
|
|
data << uint8(0); // count
|
|
data << uint32(0); // unk
|
|
player->GetSession()->SendPacket(&data);
|
|
|
|
SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK);
|
|
}
|
|
|
|
void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ACCEPT");
|
|
|
|
recv_data.read_skip<uint32>();
|
|
Group* group = GetPlayer()->GetGroupInvite();
|
|
|
|
if (!group)
|
|
return;
|
|
|
|
// Remove player from invitees in any case
|
|
group->RemoveInvite(GetPlayer());
|
|
|
|
if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
// Group is full
|
|
if (group->IsFull())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
|
|
return;
|
|
}
|
|
|
|
Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
|
|
|
|
// Forming a new group, create it
|
|
if (!group->IsCreated())
|
|
{
|
|
// This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
|
|
if (!leader)
|
|
{
|
|
group->RemoveAllInvites();
|
|
return;
|
|
}
|
|
|
|
// If we're about to create a group there really should be a leader present
|
|
ASSERT(leader);
|
|
group->RemoveInvite(leader);
|
|
group->Create(leader);
|
|
sGroupMgr->AddGroup(group);
|
|
}
|
|
|
|
// Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
|
|
if (!group->AddMember(GetPlayer()))
|
|
return;
|
|
|
|
group->BroadcastGroupUpdate();
|
|
}
|
|
|
|
void WorldSession::HandleGroupDeclineOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DECLINE");
|
|
|
|
Group* group = GetPlayer()->GetGroupInvite();
|
|
if (!group)
|
|
return;
|
|
|
|
// Remember leader if online (group pointer will be invalid if group gets disbanded)
|
|
Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
|
|
|
|
// uninvite, group can be deleted
|
|
GetPlayer()->UninviteFromGroup();
|
|
|
|
if (!leader || !leader->GetSession())
|
|
return;
|
|
|
|
// report
|
|
std::string name = std::string(GetPlayer()->GetName());
|
|
WorldPacket data(SMSG_GROUP_DECLINE, name.length());
|
|
data << name.c_str();
|
|
leader->GetSession()->SendPacket(&data);
|
|
}
|
|
|
|
void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_UNINVITE_GUID");
|
|
|
|
uint64 guid;
|
|
std::string reason;
|
|
recv_data >> guid;
|
|
recv_data >> reason;
|
|
|
|
//can't uninvite yourself
|
|
if (guid == GetPlayer()->GetGUID())
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleGroupUninviteGuidOpcode: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
PartyResult res = GetPlayer()->CanUninviteFromGroup();
|
|
if (res != ERR_PARTY_RESULT_OK)
|
|
{
|
|
SendPartyResult(PARTY_OP_UNINVITE, "", res);
|
|
return;
|
|
}
|
|
|
|
Group* grp = GetPlayer()->GetGroup();
|
|
if (!grp)
|
|
return;
|
|
|
|
if (grp->IsLeader(guid))
|
|
{
|
|
SendPartyResult(PARTY_OP_UNINVITE, "", ERR_NOT_LEADER);
|
|
return;
|
|
}
|
|
|
|
if (grp->IsMember(guid))
|
|
{
|
|
Player::RemoveFromGroup(grp, guid, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID(), reason.c_str());
|
|
return;
|
|
}
|
|
|
|
if (Player* player = grp->GetInvited(guid))
|
|
{
|
|
player->UninviteFromGroup();
|
|
return;
|
|
}
|
|
|
|
SendPartyResult(PARTY_OP_UNINVITE, "", ERR_TARGET_NOT_IN_GROUP_S);
|
|
}
|
|
|
|
void WorldSession::HandleGroupUninviteOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_UNINVITE");
|
|
|
|
std::string membername;
|
|
recv_data >> membername;
|
|
|
|
// player not found
|
|
if (!normalizePlayerName(membername))
|
|
return;
|
|
|
|
// can't uninvite yourself
|
|
if (GetPlayer()->GetName() == membername)
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::HandleGroupUninviteOpcode: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
PartyResult res = GetPlayer()->CanUninviteFromGroup();
|
|
if (res != ERR_PARTY_RESULT_OK)
|
|
{
|
|
SendPartyResult(PARTY_OP_UNINVITE, "", res);
|
|
return;
|
|
}
|
|
|
|
Group* grp = GetPlayer()->GetGroup();
|
|
if (!grp)
|
|
return;
|
|
|
|
if (uint64 guid = grp->GetMemberGUID(membername))
|
|
{
|
|
Player::RemoveFromGroup(grp, guid, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID());
|
|
return;
|
|
}
|
|
|
|
if (Player* player = grp->GetInvited(membername))
|
|
{
|
|
player->UninviteFromGroup();
|
|
return;
|
|
}
|
|
|
|
SendPartyResult(PARTY_OP_UNINVITE, membername, ERR_TARGET_NOT_IN_GROUP_S);
|
|
}
|
|
|
|
void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SET_LEADER");
|
|
|
|
uint64 guid;
|
|
recv_data >> guid;
|
|
|
|
Player* player = ObjectAccessor::FindPlayer(guid);
|
|
Group* group = GetPlayer()->GetGroup();
|
|
|
|
if (!group || !player)
|
|
return;
|
|
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()) || player->GetGroup() != group)
|
|
return;
|
|
|
|
// Everything's fine, accepted.
|
|
group->ChangeLeader(guid);
|
|
group->SendUpdate();
|
|
}
|
|
|
|
void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DISBAND");
|
|
|
|
Group* grp = GetPlayer()->GetGroup();
|
|
if (!grp)
|
|
return;
|
|
|
|
if (_player->InBattleground())
|
|
{
|
|
SendPartyResult(PARTY_OP_INVITE, "", ERR_INVITE_RESTRICTED);
|
|
return;
|
|
}
|
|
|
|
/** error handling **/
|
|
/********************/
|
|
|
|
// everything's fine, do it
|
|
SendPartyResult(PARTY_OP_LEAVE, GetPlayer()->GetName(), ERR_PARTY_RESULT_OK);
|
|
|
|
GetPlayer()->RemoveFromGroup(GROUP_REMOVEMETHOD_LEAVE);
|
|
}
|
|
|
|
void WorldSession::HandleLootMethodOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_LOOT_METHOD");
|
|
|
|
uint32 lootMethod;
|
|
uint64 lootMaster;
|
|
uint32 lootThreshold;
|
|
recv_data >> lootMethod >> lootMaster >> lootThreshold;
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
/** error handling **/
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()))
|
|
return;
|
|
/********************/
|
|
|
|
// everything's fine, do it
|
|
group->SetLootMethod((LootMethod)lootMethod);
|
|
group->SetLooterGuid(lootMaster);
|
|
group->SetLootThreshold((ItemQualities)lootThreshold);
|
|
group->SendUpdate();
|
|
}
|
|
|
|
void WorldSession::HandleLootRoll(WorldPacket& recvData)
|
|
{
|
|
uint64 guid;
|
|
uint32 itemSlot;
|
|
uint8 rollType;
|
|
recvData >> guid; // guid of the item rolled
|
|
recvData >> itemSlot;
|
|
recvData >> rollType; // 0: pass, 1: need, 2: greed
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
group->CountRollVote(GetPlayer()->GetGUID(), guid, rollType);
|
|
|
|
switch (rollType)
|
|
{
|
|
case ROLL_NEED:
|
|
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1);
|
|
break;
|
|
case ROLL_GREED:
|
|
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_MINIMAP_PING");
|
|
|
|
if (!GetPlayer()->GetGroup())
|
|
return;
|
|
|
|
float x, y;
|
|
recv_data >> x;
|
|
recv_data >> y;
|
|
|
|
//sLog->outDebug("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
|
|
|
|
/** error handling **/
|
|
/********************/
|
|
|
|
// everything's fine, do it
|
|
WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
|
|
data << uint64(GetPlayer()->GetGUID());
|
|
data << float(x);
|
|
data << float(y);
|
|
GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID());
|
|
}
|
|
|
|
void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_RANDOM_ROLL");
|
|
|
|
uint32 minimum, maximum, roll;
|
|
recv_data >> minimum;
|
|
recv_data >> maximum;
|
|
|
|
/** error handling **/
|
|
if (minimum > maximum || maximum > 10000) // < 32768 for urand call
|
|
return;
|
|
/********************/
|
|
|
|
// everything's fine, do it
|
|
roll = urand(minimum, maximum);
|
|
|
|
//sLog->outDebug("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
|
|
|
|
WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8);
|
|
data << uint32(minimum);
|
|
data << uint32(maximum);
|
|
data << uint32(roll);
|
|
data << uint64(GetPlayer()->GetGUID());
|
|
if (GetPlayer()->GetGroup())
|
|
GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
|
|
else
|
|
SendPacket(&data);
|
|
}
|
|
|
|
void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_RAID_TARGET_UPDATE");
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
uint8 x;
|
|
recv_data >> x;
|
|
|
|
/** error handling **/
|
|
/********************/
|
|
|
|
// everything's fine, do it
|
|
if (x == 0xFF) // target icon request
|
|
{
|
|
group->SendTargetIconList(this);
|
|
}
|
|
else // target icon update
|
|
{
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
|
|
return;
|
|
|
|
uint64 guid;
|
|
recv_data >> guid;
|
|
group->SetTargetIcon(x, _player->GetGUID(), guid);
|
|
}
|
|
}
|
|
|
|
void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_RAID_CONVERT");
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
if (_player->InBattleground())
|
|
return;
|
|
|
|
/** error handling **/
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2)
|
|
return;
|
|
/********************/
|
|
|
|
// everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code)
|
|
SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK);
|
|
group->ConvertToRaid();
|
|
}
|
|
|
|
void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_CHANGE_SUB_GROUP");
|
|
|
|
// we will get correct pointer for group here, so we don't have to check if group is BG raid
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
std::string name;
|
|
uint8 groupNr;
|
|
recv_data >> name;
|
|
recv_data >> groupNr;
|
|
|
|
if (groupNr >= MAX_RAID_SUBGROUPS)
|
|
return;
|
|
|
|
uint64 senderGuid = GetPlayer()->GetGUID();
|
|
if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
|
|
return;
|
|
|
|
if (!group->HasFreeSlotSubGroup(groupNr))
|
|
return;
|
|
|
|
Player* movedPlayer = sObjectAccessor->FindPlayerByName(name.c_str());
|
|
uint64 guid;
|
|
if (movedPlayer)
|
|
{
|
|
guid = movedPlayer->GetGUID();
|
|
}
|
|
else
|
|
{
|
|
CharacterDatabase.EscapeString(name);
|
|
guid = sObjectMgr->GetPlayerGUIDByName(name.c_str());
|
|
}
|
|
|
|
group->ChangeMembersGroup(guid, groupNr);
|
|
}
|
|
|
|
void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ASSISTANT_LEADER");
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()))
|
|
return;
|
|
|
|
uint64 guid;
|
|
bool apply;
|
|
recv_data >> guid;
|
|
recv_data >> apply;
|
|
|
|
group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT);
|
|
|
|
group->SendUpdate();
|
|
}
|
|
|
|
void WorldSession::HandlePartyAssignmentOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_PARTY_ASSIGNMENT");
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
uint64 senderGuid = GetPlayer()->GetGUID();
|
|
if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
|
|
return;
|
|
|
|
uint8 assignment;
|
|
bool apply;
|
|
uint64 guid;
|
|
recv_data >> assignment >> apply;
|
|
recv_data >> guid;
|
|
|
|
switch (assignment)
|
|
{
|
|
case GROUP_ASSIGN_MAINASSIST:
|
|
group->RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINASSIST);
|
|
group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_MAINASSIST);
|
|
break;
|
|
case GROUP_ASSIGN_MAINTANK:
|
|
group->RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINTANK); // Remove main assist flag from current if any.
|
|
group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_MAINTANK);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
group->SendUpdate();
|
|
}
|
|
|
|
void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_RAID_READY_CHECK");
|
|
|
|
Group* group = GetPlayer()->GetGroup();
|
|
if (!group)
|
|
return;
|
|
|
|
if (recv_data.empty()) // request
|
|
{
|
|
/** error handling **/
|
|
if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
|
|
return;
|
|
/********************/
|
|
|
|
// everything's fine, do it
|
|
WorldPacket data(MSG_RAID_READY_CHECK, 8);
|
|
data << GetPlayer()->GetGUID();
|
|
group->BroadcastPacket(&data, false, -1);
|
|
|
|
group->OfflineReadyCheck();
|
|
}
|
|
else // answer
|
|
{
|
|
uint8 state;
|
|
recv_data >> state;
|
|
|
|
// everything's fine, do it
|
|
WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9);
|
|
data << uint64(GetPlayer()->GetGUID());
|
|
data << uint8(state);
|
|
group->BroadcastReadyCheck(&data);
|
|
}
|
|
}
|
|
|
|
void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
//Group* group = GetPlayer()->GetGroup();
|
|
//if (!group)
|
|
// return;
|
|
|
|
//if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
|
|
// return;
|
|
|
|
// Is any reaction need?
|
|
}
|
|
|
|
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data)
|
|
{
|
|
uint32 mask = player->GetGroupUpdateFlag();
|
|
|
|
if (mask == GROUP_UPDATE_FLAG_NONE)
|
|
return;
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also
|
|
mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
|
|
mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
|
|
|
|
uint32 byteCount = 0;
|
|
for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
|
|
if (mask & (1 << i))
|
|
byteCount += GroupUpdateLength[i];
|
|
|
|
data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
|
|
data->append(player->GetPackGUID());
|
|
*data << (uint32) mask;
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_STATUS)
|
|
{
|
|
if (player)
|
|
{
|
|
if (player->IsPvP())
|
|
*data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP);
|
|
else
|
|
*data << (uint16) MEMBER_STATUS_ONLINE;
|
|
}
|
|
else
|
|
*data << (uint16) MEMBER_STATUS_OFFLINE;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_CUR_HP)
|
|
*data << (uint32) player->GetHealth();
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_MAX_HP)
|
|
*data << (uint32) player->GetMaxHealth();
|
|
|
|
Powers powerType = player->getPowerType();
|
|
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
|
|
*data << (uint8) powerType;
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
|
|
*data << (uint16) player->GetPower(powerType);
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
|
|
*data << (uint16) player->GetMaxPower(powerType);
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_LEVEL)
|
|
*data << (uint16) player->getLevel();
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_ZONE)
|
|
*data << (uint16) player->GetZoneId();
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_POSITION)
|
|
*data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY();
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_AURAS)
|
|
{
|
|
uint64 auramask = player->GetAuraUpdateMaskForRaid();
|
|
*data << uint64(auramask);
|
|
for (uint32 i = 0; i < MAX_AURAS; ++i)
|
|
{
|
|
if (auramask & (uint64(1) << i))
|
|
{
|
|
AuraApplication const* aurApp = player->GetVisibleAura(i);
|
|
*data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
|
|
*data << uint8(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Pet* pet = player->GetPet();
|
|
if (mask & GROUP_UPDATE_FLAG_PET_GUID)
|
|
{
|
|
if (pet)
|
|
*data << (uint64) pet->GetGUID();
|
|
else
|
|
*data << (uint64) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_NAME)
|
|
{
|
|
if (pet)
|
|
*data << pet->GetName();
|
|
else
|
|
*data << (uint8) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
|
|
{
|
|
if (pet)
|
|
*data << (uint16) pet->GetDisplayId();
|
|
else
|
|
*data << (uint16) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
|
|
{
|
|
if (pet)
|
|
*data << (uint32) pet->GetHealth();
|
|
else
|
|
*data << (uint32) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
|
|
{
|
|
if (pet)
|
|
*data << (uint32) pet->GetMaxHealth();
|
|
else
|
|
*data << (uint32) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
|
|
{
|
|
if (pet)
|
|
*data << (uint8) pet->getPowerType();
|
|
else
|
|
*data << (uint8) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
|
|
{
|
|
if (pet)
|
|
*data << (uint16) pet->GetPower(pet->getPowerType());
|
|
else
|
|
*data << (uint16) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
|
|
{
|
|
if (pet)
|
|
*data << (uint16) pet->GetMaxPower(pet->getPowerType());
|
|
else
|
|
*data << (uint16) 0;
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
|
|
{
|
|
if (Vehicle* veh = player->GetVehicle())
|
|
*data << (uint32) veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat];
|
|
}
|
|
|
|
if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
|
|
{
|
|
if (pet)
|
|
{
|
|
uint64 auramask = pet->GetAuraUpdateMaskForRaid();
|
|
*data << uint64(auramask);
|
|
for (uint32 i = 0; i < MAX_AURAS; ++i)
|
|
{
|
|
if (auramask & (uint64(1) << i))
|
|
{
|
|
AuraApplication const* aurApp = player->GetVisibleAura(i);
|
|
*data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
|
|
*data << uint8(1);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
*data << (uint64) 0;
|
|
}
|
|
}
|
|
|
|
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
|
|
void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
|
|
uint64 Guid;
|
|
recv_data >> Guid;
|
|
|
|
Player* player = HashMapHolder<Player>::Find(Guid);
|
|
if (!player)
|
|
{
|
|
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
|
|
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
|
|
data.appendPackGUID(Guid);
|
|
data << (uint32) GROUP_UPDATE_FLAG_STATUS;
|
|
data << (uint16) MEMBER_STATUS_OFFLINE;
|
|
SendPacket(&data);
|
|
return;
|
|
}
|
|
|
|
Pet* pet = player->GetPet();
|
|
|
|
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
|
|
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
|
|
data.append(player->GetPackGUID());
|
|
|
|
uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF
|
|
if (pet)
|
|
mask1 = 0x7FFFFFFF; // for hunters and other classes with pets
|
|
|
|
Powers powerType = player->getPowerType();
|
|
data << (uint32) mask1; // group update mask
|
|
data << (uint16) MEMBER_STATUS_ONLINE; // member's online status
|
|
data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP
|
|
data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP
|
|
data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE
|
|
data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER
|
|
data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER
|
|
data << (uint16) player->getLevel(); // GROUP_UPDATE_FLAG_LEVEL
|
|
data << (uint16) player->GetZoneId(); // GROUP_UPDATE_FLAG_ZONE
|
|
data << (uint16) player->GetPositionX(); // GROUP_UPDATE_FLAG_POSITION
|
|
data << (uint16) player->GetPositionY(); // GROUP_UPDATE_FLAG_POSITION
|
|
|
|
uint64 auramask = 0;
|
|
size_t maskPos = data.wpos();
|
|
data << (uint64) auramask; // placeholder
|
|
for (uint8 i = 0; i < MAX_AURAS; ++i)
|
|
{
|
|
if (AuraApplication * aurApp = player->GetVisibleAura(i))
|
|
{
|
|
auramask |= (uint64(1) << i);
|
|
data << (uint32) aurApp->GetBase()->GetId();
|
|
data << (uint8) 1;
|
|
}
|
|
}
|
|
data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
|
|
|
|
if (pet)
|
|
{
|
|
Powers petpowertype = pet->getPowerType();
|
|
data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID
|
|
data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME
|
|
data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID
|
|
data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP
|
|
data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP
|
|
data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE
|
|
data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER
|
|
data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER
|
|
|
|
uint64 petauramask = 0;
|
|
size_t petMaskPos = data.wpos();
|
|
data << (uint64) petauramask; // placeholder
|
|
for (uint8 i = 0; i < MAX_AURAS; ++i)
|
|
{
|
|
if (AuraApplication * auraApp = pet->GetVisibleAura(i))
|
|
{
|
|
petauramask |= (uint64(1) << i);
|
|
data << (uint32) auraApp->GetBase()->GetId();
|
|
data << (uint8) 1;
|
|
}
|
|
}
|
|
data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS
|
|
}
|
|
else
|
|
{
|
|
data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME
|
|
data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS
|
|
}
|
|
|
|
SendPacket(&data);
|
|
}
|
|
|
|
/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
// every time the player checks the character screen
|
|
_player->SendRaidInfo();
|
|
}
|
|
|
|
/*void WorldSession::HandleGroupCancelOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug("WORLD: got CMSG_GROUP_CANCEL.");
|
|
}*/
|
|
|
|
void WorldSession::HandleOptOutOfLootOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_OPT_OUT_OF_LOOT");
|
|
|
|
uint32 passOnLoot;
|
|
recv_data >> passOnLoot; // 1 always pass, 0 do not pass
|
|
|
|
// ignore if player not loaded
|
|
if (!GetPlayer()) // needed because STATUS_AUTHED
|
|
{
|
|
if (passOnLoot != 0)
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
|
|
return;
|
|
}
|
|
|
|
GetPlayer()->SetPassOnGroupLoot(passOnLoot);
|
|
}
|