- 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
792 lines
31 KiB
C++
Executable File
792 lines
31 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 "ObjectAccessor.h"
|
|
#include "ObjectMgr.h"
|
|
#include "ArenaTeamMgr.h"
|
|
#include "WorldPacket.h"
|
|
#include "WorldSession.h"
|
|
|
|
#include "ArenaTeam.h"
|
|
#include "BattlegroundMgr.h"
|
|
#include "Battleground.h"
|
|
#include "Chat.h"
|
|
#include "Language.h"
|
|
#include "Log.h"
|
|
#include "Player.h"
|
|
#include "Object.h"
|
|
#include "Opcodes.h"
|
|
#include "DisableMgr.h"
|
|
#include "Group.h"
|
|
|
|
void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recv_data)
|
|
{
|
|
uint64 guid;
|
|
recv_data >> guid;
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)));
|
|
|
|
Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
|
|
if (!unit)
|
|
return;
|
|
|
|
if (!unit->isBattleMaster()) // it's not battlemaster
|
|
return;
|
|
|
|
// Stop the npc if moving
|
|
unit->StopMoving();
|
|
|
|
BattlegroundTypeId bgTypeId = sBattlegroundMgr->GetBattleMasterBG(unit->GetEntry());
|
|
|
|
if (!_player->GetBGAccessByLevel(bgTypeId))
|
|
{
|
|
// temp, must be gossip message...
|
|
SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR);
|
|
return;
|
|
}
|
|
|
|
SendBattleGroundList(guid, bgTypeId);
|
|
}
|
|
|
|
void WorldSession::SendBattleGroundList(uint64 guid, BattlegroundTypeId bgTypeId)
|
|
{
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildBattlegroundListPacket(&data, guid, _player, bgTypeId, 0);
|
|
SendPacket(&data);
|
|
}
|
|
|
|
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data)
|
|
{
|
|
uint64 guid;
|
|
uint32 bgTypeId_;
|
|
uint32 instanceId;
|
|
uint8 joinAsGroup;
|
|
bool isPremade = false;
|
|
Group* grp = NULL;
|
|
|
|
recv_data >> guid; // battlemaster guid
|
|
recv_data >> bgTypeId_; // battleground type id (DBC id)
|
|
recv_data >> instanceId; // instance id, 0 if First Available selected
|
|
recv_data >> joinAsGroup; // join as group
|
|
|
|
if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL))
|
|
{
|
|
ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED);
|
|
return;
|
|
}
|
|
|
|
BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
|
|
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)));
|
|
|
|
// can do this, since it's battleground, not arena
|
|
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0);
|
|
BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0);
|
|
|
|
// ignore if player is already in BG
|
|
if (_player->InBattleground())
|
|
return;
|
|
|
|
// get bg instance or bg template if instance not found
|
|
Battleground* bg = NULL;
|
|
if (instanceId)
|
|
bg = sBattlegroundMgr->GetBattlegroundThroughClientInstance(instanceId, bgTypeId);
|
|
|
|
if (!bg)
|
|
bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
|
|
if (!bg)
|
|
return;
|
|
|
|
// expected bracket entry
|
|
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
|
|
if (!bracketEntry)
|
|
return;
|
|
|
|
GroupJoinBattlegroundResult err;
|
|
|
|
// check queue conditions
|
|
if (!joinAsGroup)
|
|
{
|
|
if (GetPlayer()->isUsingLfg())
|
|
{
|
|
// player is using dungeon finder or raid finder
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_LFG_CANT_USE_BATTLEGROUND);
|
|
GetPlayer()->GetSession()->SendPacket(&data);
|
|
return;
|
|
}
|
|
|
|
// check Deserter debuff
|
|
if (!_player->CanJoinToBattleground())
|
|
{
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
|
|
_player->GetSession()->SendPacket(&data);
|
|
return;
|
|
}
|
|
|
|
if (_player->GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
|
{
|
|
//player is already in random queue
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG);
|
|
_player->GetSession()->SendPacket(&data);
|
|
return;
|
|
}
|
|
|
|
if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB)
|
|
{
|
|
//player is already in queue, can't start random queue
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG);
|
|
_player->GetSession()->SendPacket(&data);
|
|
return;
|
|
}
|
|
|
|
// check if already in queue
|
|
if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
|
//player is already in this queue
|
|
return;
|
|
|
|
// check if has free queue slots
|
|
if (!_player->HasFreeBattlegroundQueueId())
|
|
{
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES);
|
|
_player->GetSession()->SendPacket(&data);
|
|
return;
|
|
}
|
|
|
|
BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId];
|
|
|
|
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
|
|
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
|
|
// already checked if queueSlot is valid, now just get it
|
|
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
|
|
|
|
WorldPacket data;
|
|
// send status packet (in queue)
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType);
|
|
SendPacket(&data);
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName());
|
|
}
|
|
else
|
|
{
|
|
grp = _player->GetGroup();
|
|
// no group found, error
|
|
if (!grp)
|
|
return;
|
|
if (grp->GetLeaderGUID() != _player->GetGUID())
|
|
return;
|
|
err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
|
|
isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());
|
|
|
|
BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId];
|
|
GroupQueueInfo* ginfo = NULL;
|
|
uint32 avgTime = 0;
|
|
|
|
if (err > 0)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: the following players are joining as group:");
|
|
ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
|
|
avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
|
|
}
|
|
|
|
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
|
{
|
|
Player* member = itr->getSource();
|
|
if (!member)
|
|
continue; // this should never happen
|
|
|
|
WorldPacket data;
|
|
|
|
if (err <= 0)
|
|
{
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
|
|
member->GetSession()->SendPacket(&data);
|
|
continue;
|
|
}
|
|
|
|
// add to queue
|
|
uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
|
|
|
|
// send status packet (in queue)
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType);
|
|
member->GetSession()->SendPacket(&data);
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
|
|
member->GetSession()->SendPacket(&data);
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName());
|
|
}
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: group end");
|
|
|
|
}
|
|
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
|
|
}
|
|
|
|
void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
|
|
|
|
Battleground* bg = _player->GetBattleground();
|
|
if (!bg) // can't be received if player not in battleground
|
|
return;
|
|
|
|
uint32 count = 0;
|
|
Player* aplr = NULL;
|
|
Player* hplr = NULL;
|
|
|
|
if (uint64 guid = bg->GetFlagPickerGUID(BG_TEAM_ALLIANCE))
|
|
{
|
|
aplr = ObjectAccessor::FindPlayer(guid);
|
|
if (aplr)
|
|
++count;
|
|
}
|
|
|
|
if (uint64 guid = bg->GetFlagPickerGUID(BG_TEAM_HORDE))
|
|
{
|
|
hplr = ObjectAccessor::FindPlayer(guid);
|
|
if (hplr)
|
|
++count;
|
|
}
|
|
|
|
WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, 4 + 4 + 16 * count);
|
|
data << 0;
|
|
data << count;
|
|
if (aplr)
|
|
{
|
|
data << uint64(aplr->GetGUID());
|
|
data << float(aplr->GetPositionX());
|
|
data << float(aplr->GetPositionY());
|
|
}
|
|
|
|
if (hplr)
|
|
{
|
|
data << uint64(hplr->GetGUID());
|
|
data << float(hplr->GetPositionX());
|
|
data << float(hplr->GetPositionY());
|
|
}
|
|
|
|
SendPacket(&data);
|
|
}
|
|
|
|
void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd MSG_PVP_LOG_DATA Message");
|
|
|
|
Battleground* bg = _player->GetBattleground();
|
|
if (!bg)
|
|
return;
|
|
|
|
// Prevent players from sending BuildPvpLogDataPacket in an arena except for when sent in BattleGround::EndBattleGround.
|
|
if (bg->isArena())
|
|
return;
|
|
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildPvpLogDataPacket(&data, bg);
|
|
SendPacket(&data);
|
|
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent MSG_PVP_LOG_DATA Message");
|
|
}
|
|
|
|
void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
|
|
|
|
uint32 bgTypeId;
|
|
recv_data >> bgTypeId; // id from DBC
|
|
|
|
uint8 fromWhere;
|
|
recv_data >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo)
|
|
|
|
uint8 unk1;
|
|
recv_data >> unk1; // Unknown 3.2.2
|
|
|
|
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
|
|
if (!bl)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId, _player->GetName(), _player->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
WorldPacket data;
|
|
sBattlegroundMgr->BuildBattlegroundListPacket(&data, 0, _player, BattlegroundTypeId(bgTypeId), fromWhere);
|
|
SendPacket(&data);
|
|
}
|
|
|
|
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
|
|
|
|
uint8 type; // arenatype if arena
|
|
uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
|
|
uint32 bgTypeId_; // type id from dbc
|
|
uint16 unk; // 0x1F90 constant?
|
|
uint8 action; // enter battle 0x1, leave queue 0x0
|
|
|
|
recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action;
|
|
|
|
if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: invalid bgtype (%u) with player (Name: %s, GUID: %u) received.", bgTypeId_, _player->GetName(), _player->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
if (!_player->InBattlegroundQueue())
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (Name: %s, GUID: %u), he is not in bg_queue.", _player->GetName(), _player->GetGUIDLow());
|
|
return;
|
|
}
|
|
|
|
//get GroupQueueInfo from BattlegroundQueue
|
|
BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
|
|
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, type);
|
|
BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId];
|
|
//we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue::RemovePlayer() function
|
|
GroupQueueInfo ginfo;
|
|
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: itrplayerstatus not found.");
|
|
return;
|
|
}
|
|
// if action == 1, then instanceId is required
|
|
if (!ginfo.IsInvitedToBGInstanceGUID && action == 1)
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: instance not found.");
|
|
return;
|
|
}
|
|
|
|
Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
|
|
|
|
// bg template might and must be used in case of leaving queue, when instance is not created yet
|
|
if (!bg && action == 0)
|
|
bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
|
|
if (!bg)
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "BattlegroundHandler: bg_template not found for type id %u.", bgTypeId);
|
|
return;
|
|
}
|
|
|
|
// expected bracket entry
|
|
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
|
|
if (!bracketEntry)
|
|
return;
|
|
|
|
//some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
|
|
if (action == 1 && ginfo.ArenaType == 0)
|
|
{
|
|
//if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
|
|
if (!_player->CanJoinToBattleground())
|
|
{
|
|
//send bg command result to show nice message
|
|
WorldPacket data2;
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
|
|
_player->GetSession()->SendPacket(&data2);
|
|
action = 0;
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
|
|
}
|
|
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
|
|
if (_player->getLevel() > bg->GetMaxLevel())
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
|
|
_player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
|
|
action = 0;
|
|
}
|
|
}
|
|
uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
|
|
WorldPacket data;
|
|
switch (action)
|
|
{
|
|
case 1: // port to battleground
|
|
if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
|
|
return; // cheating?
|
|
|
|
if (!_player->InBattleground())
|
|
_player->SetBattlegroundEntryPoint();
|
|
|
|
// resurrect the player
|
|
if (!_player->isAlive())
|
|
{
|
|
_player->ResurrectPlayer(1.0f);
|
|
_player->SpawnCorpseBones();
|
|
}
|
|
// stop taxi flight at port
|
|
if (_player->isInFlight())
|
|
{
|
|
_player->GetMotionMaster()->MovementExpired();
|
|
_player->CleanupAfterTaxiFlight();
|
|
}
|
|
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType());
|
|
_player->GetSession()->SendPacket(&data);
|
|
// remove battleground queue status from BGmgr
|
|
bgQueue.RemovePlayer(_player->GetGUID(), false);
|
|
// this is still needed here if battleground "jumping" shouldn't add deserter debuff
|
|
// also this is required to prevent stuck at old battleground after SetBattlegroundId set to new
|
|
if (Battleground* currentBg = _player->GetBattleground())
|
|
currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
|
|
|
|
// set the destination instance id
|
|
_player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId);
|
|
// set the destination team
|
|
_player->SetBGTeam(ginfo.Team);
|
|
// bg->HandleBeforeTeleportToBattleground(_player);
|
|
sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
|
|
// add only in HandleMoveWorldPortAck()
|
|
// bg->AddPlayer(_player, team);
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
|
|
break;
|
|
case 0: // leave queue
|
|
// if player leaves rated arena match before match start, it is counted as he played but he lost
|
|
if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID)
|
|
{
|
|
ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ginfo.Team);
|
|
if (at)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating);
|
|
at->MemberLost(_player, ginfo.OpponentsMatchmakerRating);
|
|
at->SaveToDB();
|
|
}
|
|
}
|
|
_player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0);
|
|
bgQueue.RemovePlayer(_player->GetGUID(), true);
|
|
// player left queue, we should update it - do not update Arena Queue
|
|
if (!ginfo.ArenaType)
|
|
sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
|
|
SendPacket(&data);
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
|
|
break;
|
|
default:
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "Battleground port: unknown action %u", action);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WorldSession::HandleLeaveBattlefieldOpcode(WorldPacket& recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
|
|
|
|
recv_data.read_skip<uint8>(); // unk1
|
|
recv_data.read_skip<uint8>(); // unk2
|
|
recv_data.read_skip<uint32>(); // BattlegroundTypeId
|
|
recv_data.read_skip<uint16>(); // unk3
|
|
|
|
// not allow leave battleground in combat
|
|
if (_player->isInCombat())
|
|
if (Battleground* bg = _player->GetBattleground())
|
|
if (bg->GetStatus() != STATUS_WAIT_LEAVE)
|
|
return;
|
|
|
|
_player->LeaveBattleground();
|
|
}
|
|
|
|
void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/)
|
|
{
|
|
// empty opcode
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Battleground status");
|
|
|
|
WorldPacket data;
|
|
// we must update all queues here
|
|
Battleground* bg = NULL;
|
|
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
|
|
{
|
|
BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i);
|
|
if (!bgQueueTypeId)
|
|
continue;
|
|
BattlegroundTypeId bgTypeId = BattlegroundMgr::BGTemplateId(bgQueueTypeId);
|
|
uint8 arenaType = BattlegroundMgr::BGArenaType(bgQueueTypeId);
|
|
if (bgTypeId == _player->GetBattlegroundTypeId())
|
|
{
|
|
bg = _player->GetBattleground();
|
|
//i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
|
|
//so i must use bg pointer to get that information
|
|
if (bg && bg->GetArenaType() == arenaType)
|
|
{
|
|
// this line is checked, i only don't know if GetStartTime is changing itself after bg end!
|
|
// send status in Battleground
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType);
|
|
SendPacket(&data);
|
|
continue;
|
|
}
|
|
}
|
|
//we are sending update to player about queue - he can be invited there!
|
|
//get GroupQueueInfo for queue status
|
|
BattlegroundQueue& bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId];
|
|
GroupQueueInfo ginfo;
|
|
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
|
|
continue;
|
|
if (ginfo.IsInvitedToBGInstanceGUID)
|
|
{
|
|
bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
|
|
if (!bg)
|
|
continue;
|
|
uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime);
|
|
// send status invited to Battleground
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType);
|
|
SendPacket(&data);
|
|
}
|
|
else
|
|
{
|
|
bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
|
|
if (!bg)
|
|
continue;
|
|
|
|
// expected bracket entry
|
|
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
|
|
if (!bracketEntry)
|
|
continue;
|
|
|
|
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId());
|
|
// send status in Battleground Queue
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType);
|
|
SendPacket(&data);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
|
|
|
|
Battleground* bg = _player->GetBattleground();
|
|
|
|
uint64 guid;
|
|
recv_data >> guid;
|
|
|
|
Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
|
|
if (!unit)
|
|
return;
|
|
|
|
if (!unit->isSpiritService()) // it's not spirit service
|
|
return;
|
|
|
|
if (bg)
|
|
sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, guid);
|
|
}
|
|
|
|
void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
|
|
|
|
Battleground* bg = _player->GetBattleground();
|
|
|
|
uint64 guid;
|
|
recv_data >> guid;
|
|
|
|
Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
|
|
if (!unit)
|
|
return;
|
|
|
|
if (!unit->isSpiritService()) // it's not spirit service
|
|
return;
|
|
|
|
if (bg)
|
|
bg->AddPlayerToResurrectQueue(guid, _player->GetGUID());
|
|
}
|
|
|
|
void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
|
|
|
|
uint64 guid; // arena Battlemaster guid
|
|
uint8 arenaslot; // 2v2, 3v3 or 5v5
|
|
uint8 asGroup; // asGroup
|
|
uint8 isRated; // isRated
|
|
Group* grp = NULL;
|
|
|
|
recv_data >> guid >> arenaslot >> asGroup >> isRated;
|
|
|
|
// ignore if we already in BG or BG queue
|
|
if (_player->InBattleground())
|
|
return;
|
|
|
|
Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
|
|
if (!unit)
|
|
return;
|
|
|
|
if (!unit->isBattleMaster()) // it's not battle master
|
|
return;
|
|
|
|
uint8 arenatype = 0;
|
|
uint32 arenaRating = 0;
|
|
uint32 matchmakerRating = 0;
|
|
|
|
switch (arenaslot)
|
|
{
|
|
case 0:
|
|
arenatype = ARENA_TYPE_2v2;
|
|
break;
|
|
case 1:
|
|
arenatype = ARENA_TYPE_3v3;
|
|
break;
|
|
case 2:
|
|
arenatype = ARENA_TYPE_5v5;
|
|
break;
|
|
default:
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot);
|
|
return;
|
|
}
|
|
|
|
//check existance
|
|
Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
|
|
if (!bg)
|
|
{
|
|
sLog->outError(LOG_FILTER_NETWORKIO, "Battleground: template bg (all arenas) not found");
|
|
return;
|
|
}
|
|
|
|
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, NULL))
|
|
{
|
|
ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED);
|
|
return;
|
|
}
|
|
|
|
BattlegroundTypeId bgTypeId = bg->GetTypeID();
|
|
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype);
|
|
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
|
|
if (!bracketEntry)
|
|
return;
|
|
|
|
GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL;
|
|
|
|
if (!asGroup)
|
|
{
|
|
// check if already in queue
|
|
if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
|
//player is already in this queue
|
|
return;
|
|
// check if has free queue slots
|
|
if (!_player->HasFreeBattlegroundQueueId())
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
grp = _player->GetGroup();
|
|
// no group found, error
|
|
if (!grp)
|
|
return;
|
|
if (grp->GetLeaderGUID() != _player->GetGUID())
|
|
return;
|
|
err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot);
|
|
}
|
|
|
|
uint32 ateamId = 0;
|
|
|
|
if (isRated)
|
|
{
|
|
ateamId = _player->GetArenaTeamId(arenaslot);
|
|
// check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
|
|
ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
|
|
if (!at)
|
|
{
|
|
_player->GetSession()->SendNotInArenaTeamPacket(arenatype);
|
|
return;
|
|
}
|
|
// get the team rating for queueing
|
|
arenaRating = at->GetRating();
|
|
matchmakerRating = at->GetAverageMMR(grp);
|
|
// the arenateam id must match for everyone in the group
|
|
|
|
if (arenaRating <= 0)
|
|
arenaRating = 1;
|
|
}
|
|
|
|
BattlegroundQueue &bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId];
|
|
if (asGroup)
|
|
{
|
|
uint32 avgTime = 0;
|
|
|
|
if (err > 0)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: arena join as group start");
|
|
if (isRated)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName(), matchmakerRating, arenatype);
|
|
bg->SetRated(true);
|
|
}
|
|
else
|
|
bg->SetRated(false);
|
|
|
|
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId);
|
|
avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
|
|
}
|
|
|
|
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
|
{
|
|
Player* member = itr->getSource();
|
|
if (!member)
|
|
continue;
|
|
|
|
WorldPacket data;
|
|
|
|
if (err <= 0)
|
|
{
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
|
|
member->GetSession()->SendPacket(&data);
|
|
continue;
|
|
}
|
|
|
|
// add to queue
|
|
uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
|
|
|
|
// send status packet (in queue)
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype);
|
|
member->GetSession()->SendPacket(&data);
|
|
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
|
|
member->GetSession()->SendPacket(&data);
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId);
|
|
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
|
|
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
|
|
|
|
WorldPacket data;
|
|
// send status packet (in queue)
|
|
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype);
|
|
SendPacket(&data);
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName());
|
|
}
|
|
sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
|
|
}
|
|
|
|
void WorldSession::HandleReportPvPAFK(WorldPacket & recv_data)
|
|
{
|
|
uint64 playerGuid;
|
|
recv_data >> playerGuid;
|
|
Player* reportedPlayer = ObjectAccessor::FindPlayer(playerGuid);
|
|
|
|
if (!reportedPlayer)
|
|
{
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "WorldSession::HandleReportPvPAFK: player not found");
|
|
return;
|
|
}
|
|
|
|
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "WorldSession::HandleReportPvPAFK: %s reported %s", _player->GetName(), reportedPlayer->GetName());
|
|
|
|
reportedPlayer->ReportedAfkBy(_player);
|
|
}
|