diff options
| author | Spp <spp@jorge.gr> | 2012-01-31 11:49:53 +0100 |
|---|---|---|
| committer | Spp <spp@jorge.gr> | 2012-01-31 11:49:53 +0100 |
| commit | 37b66384f3d905fb8de506aae48237900a1b6065 (patch) | |
| tree | f6c36187e06f76704d7a661179857916b18b6469 /src/server/game/Server | |
| parent | fdbb3e52bcbaa236a26bd2bf8293a5deccb34a01 (diff) | |
| parent | d4670a558dd40fc03c9b143dcffa763c834ab966 (diff) | |
Merge branch 'master' into 4.x
Conflicts:
src/server/authserver/Server/AuthSocket.cpp
src/server/game/Entities/Object/Object.cpp
src/server/game/Entities/Player/Player.cpp
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Handlers/AuctionHouseHandler.cpp
src/server/game/Handlers/CharacterHandler.cpp
src/server/game/Handlers/MovementHandler.cpp
src/server/game/Miscellaneous/SharedDefines.h
src/server/game/Spells/Spell.cpp
src/server/game/Spells/SpellEffects.cpp
Diffstat (limited to 'src/server/game/Server')
36 files changed, 2 insertions, 19826 deletions
diff --git a/src/server/game/Server/Protocol/Handlers/AddonHandler.cpp b/src/server/game/Server/Protocol/Handlers/AddonHandler.cpp deleted file mode 100755 index ef537cb6198..00000000000 --- a/src/server/game/Server/Protocol/Handlers/AddonHandler.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 "zlib.h" -#include "AddonHandler.h" -#include "DatabaseEnv.h" -#include "Opcodes.h" -#include "Log.h" - -AddonHandler::AddonHandler() -{ -} - -AddonHandler::~AddonHandler() -{ -} - -bool AddonHandler::BuildAddonPacket(WorldPacket* Source, WorldPacket* Target) -{ - ByteBuffer AddOnPacked; - uLongf AddonRealSize; - uint32 CurrentPosition; - uint32 TempValue; - - unsigned char tdata[256] = - { - 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, - 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, - 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, - 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, - 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, - 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, - 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, - 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, - 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, - 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, - 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, - 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, - 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, - 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, - 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, - 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 - }; - - // broken addon packet, can't be received from real client - if (Source->rpos() + 4 > Source->size()) - return false; - - *Source >> TempValue; // get real size of the packed structure - - // empty addon packet, nothing process, can't be received from real client - if (!TempValue) - return false; - - AddonRealSize = TempValue; // temp value because ZLIB only excepts uLongf - - CurrentPosition = Source->rpos(); // get the position of the pointer in the structure - - AddOnPacked.resize(AddonRealSize); // resize target for zlib action - - if (!uncompress(const_cast<uint8*>(AddOnPacked.contents()), &AddonRealSize, const_cast<uint8*>((*Source).contents() + CurrentPosition), (*Source).size() - CurrentPosition)!= Z_OK) - { - Target->Initialize(SMSG_ADDON_INFO); - - uint32 addonsCount; - AddOnPacked >> addonsCount; // addons count? - - for (uint32 i = 0; i < addonsCount; ++i) - { - std::string addonName; - uint8 enabled; - uint32 crc, unk2; - - // check next addon data format correctness - if (AddOnPacked.rpos()+1 > AddOnPacked.size()) - return false; - - AddOnPacked >> addonName; - - // recheck next addon data format correctness - if (AddOnPacked.rpos()+1+4+4 > AddOnPacked.size()) - return false; - - AddOnPacked >> enabled >> crc >> unk2; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk2); - - uint8 state = (enabled ? 2 : 1); - *Target << uint8(state); - - uint8 unk1 = (enabled ? 1 : 0); - *Target << uint8(unk1); - if (unk1) - { - uint8 unk = (crc != 0x4c1c776d); // If addon is Standard addon CRC - *Target << uint8(unk); - if (unk) - Target->append(tdata, sizeof(tdata)); - - *Target << uint32(0); - } - - uint8 unk3 = (enabled ? 0 : 1); - *Target << uint8(unk3); - if (unk3) - { - // String, 256 (null terminated?) - *Target << uint8(0); - } - } - - uint32 unk4; - AddOnPacked >> unk4; - - uint32 count = 0; - *Target << uint32(count); - - if (AddOnPacked.rpos() != AddOnPacked.size()) - sLog->outDebug(LOG_FILTER_NETWORKIO, "packet under read!"); - } - else - { - sLog->outError("Addon packet uncompress error :("); - return false; - } - return true; -} diff --git a/src/server/game/Server/Protocol/Handlers/AddonHandler.h b/src/server/game/Server/Protocol/Handlers/AddonHandler.h deleted file mode 100755 index 36cb19e5698..00000000000 --- a/src/server/game/Server/Protocol/Handlers/AddonHandler.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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/>. - */ - -#ifndef __ADDONHANDLER_H -#define __ADDONHANDLER_H - -#include "Common.h" -#include "Config.h" -#include <ace/Singleton.h> -#include "WorldPacket.h" - -class AddonHandler -{ - /* Construction */ - friend class ACE_Singleton<AddonHandler, ACE_Null_Mutex>; - AddonHandler(); - - public: - ~AddonHandler(); - //build addon packet - bool BuildAddonPacket(WorldPacket* Source, WorldPacket* Target); -}; -#define sAddOnHandler ACE_Singleton<AddonHandler, ACE_Null_Mutex>::instance() -#endif - diff --git a/src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp b/src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp deleted file mode 100755 index 8fb820713ce..00000000000 --- a/src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * 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 "Player.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "DatabaseEnv.h" - -#include "ArenaTeam.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "SocialMgr.h" -#include "ArenaTeamMgr.h" - -void WorldSession::HandleInspectArenaTeamsOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_INSPECT_ARENA_TEAMS"); - - uint64 guid; - recvData >> guid; - sLog->outDebug(LOG_FILTER_NETWORKIO, "Inspect Arena stats (GUID: %u TypeId: %u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); - - if (Player* player = ObjectAccessor::FindPlayer(guid)) - { - for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i) - { - if (uint32 a_id = player->GetArenaTeamId(i)) - { - if (ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(a_id)) - arenaTeam->Inspect(this, player->GetGUID()); - } - } - } -} - -void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ARENA_TEAM_QUERY"); - - uint32 arenaTeamId; - recvData >> arenaTeamId; - - if (ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId)) - { - arenaTeam->Query(this); - arenaTeam->SendStats(this); - } -} - -void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ARENA_TEAM_ROSTER"); - - uint32 arenaTeamId; // arena team id - recvData >> arenaTeamId; - - if (ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId)) - arenaTeam->Roster(this); -} - -void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_INVITE"); - - uint32 arenaTeamId; // arena team id - std::string invitedName; - - Player* player = NULL; - - recvData >> arenaTeamId >> invitedName; - - if (!invitedName.empty()) - { - if (!normalizePlayerName(invitedName)) - return; - - player = sObjectAccessor->FindPlayerByName(invitedName.c_str()); - } - - if (!player) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", invitedName, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); - return; - } - - if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); - return; - } - - ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); - if (!arenaTeam) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM); - return; - } - - // OK result but don't send invite - if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - return; - - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - return; - } - - if (player->GetArenaTeamId(arenaTeam->GetSlot())) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); - return; - } - - if (player->GetArenaTeamIdInvited()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); - return; - } - - if (arenaTeam->GetMembersSize() >= arenaTeam->GetType() * 2) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, arenaTeam->GetName(), "", ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S); - return; - } - - sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), invitedName.c_str()); - - player->SetArenaTeamIdInvited(arenaTeam->GetId()); - - WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10)); - data << GetPlayer()->GetName(); - data << arenaTeam->GetName(); - player->GetSession()->SendPacket(&data); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_ARENA_TEAM_INVITE"); -} - -void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_ACCEPT"); // empty opcode - - ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(_player->GetArenaTeamIdInvited()); - if (!arenaTeam) - return; - - // Check if player is already in another team of the same size - if (_player->GetArenaTeamId(arenaTeam->GetSlot())) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - - // Only allow members of the other faction to join the team if cross faction interaction is enabled - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != sObjectMgr->GetPlayerTeamByGUID(arenaTeam->GetCaptain())) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - return; - } - - // Add player to team - if (!arenaTeam->AddMember(_player->GetGUID())) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_INTERNAL); - return; - } - - // Broadcast event - arenaTeam->BroadcastEvent(ERR_ARENA_TEAM_JOIN_SS, _player->GetGUID(), 2, _player->GetName(), arenaTeam->GetName(), ""); -} - -void WorldSession::HandleArenaTeamDeclineOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_DECLINE"); // empty opcode - - // Remove invite from player - _player->SetArenaTeamIdInvited(0); -} - -void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_LEAVE"); - - uint32 arenaTeamId; - recvData >> arenaTeamId; - - ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); - if (!arenaTeam) - return; - - // Disallow leave team while in arena - if (_player->InArena()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_INTERNAL); - return; - } - - // Team captain can't leave the team if other members are still present - if (_player->GetGUID() == arenaTeam->GetCaptain() && arenaTeam->GetMembersSize() > 1) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); - return; - } - - // If team consists only of the captain, disband the team - if (_player->GetGUID() == arenaTeam->GetCaptain()) - { - arenaTeam->Disband(this); - delete arenaTeam; - return; - } - else - arenaTeam->DelMember(_player->GetGUID(), true); - - // Broadcast event - arenaTeam->BroadcastEvent(ERR_ARENA_TEAM_LEAVE_SS, _player->GetGUID(), 2, _player->GetName(), arenaTeam->GetName(), ""); - - // Inform player who left - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, arenaTeam->GetName(), "", 0); -} - -void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_DISBAND"); - - uint32 arenaTeamId; - recvData >> arenaTeamId; - - if (ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId)) - { - // Only captain can disband the team - if (arenaTeam->GetCaptain() != _player->GetGUID()) - return; - - // Teams cannot be disbanded during fights - if (arenaTeam->IsFighting()) - return; - - arenaTeam->Disband(this); - delete arenaTeam; - } -} - -void WorldSession::HandleArenaTeamRemoveOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_REMOVE"); - - uint32 arenaTeamId; - std::string name; - - recvData >> arenaTeamId; - recvData >> name; - - // Check for valid arena team - ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); - if (!arenaTeam) - return; - - // Only captain can remove members - if (arenaTeam->GetCaptain() != _player->GetGUID()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); - return; - } - - if (!normalizePlayerName(name)) - return; - - // Check if team member exists - ArenaTeamMember* member = arenaTeam->GetMember(name); - if (!member) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); - return; - } - - // Captain cannot be removed - if (arenaTeam->GetCaptain() == member->Guid) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); - return; - } - - arenaTeam->DelMember(member->Guid, true); - - // Broadcast event - arenaTeam->BroadcastEvent(ERR_ARENA_TEAM_REMOVE_SSS, 0, 3, name, arenaTeam->GetName(), _player->GetName()); -} - -void WorldSession::HandleArenaTeamLeaderOpcode(WorldPacket & recvData) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ARENA_TEAM_LEADER"); - - uint32 arenaTeamId; - std::string name; - - recvData >> arenaTeamId; - recvData >> name; - - // Check for valid arena team - ArenaTeam* arenaTeam = sArenaTeamMgr->GetArenaTeamById(arenaTeamId); - if (!arenaTeam) - return; - - // Only captain can pass leadership - if (arenaTeam->GetCaptain() != _player->GetGUID()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); - return; - } - - if (!normalizePlayerName(name)) - return; - - // Check if team member exists - ArenaTeamMember* member = arenaTeam->GetMember(name); - if (!member) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); - return; - } - - // Check if the target is already team captain - if (arenaTeam->GetCaptain() == member->Guid) - return; - - arenaTeam->SetCaptain(member->Guid); - - // Broadcast event - arenaTeam->BroadcastEvent(ERR_ARENA_TEAM_LEADER_CHANGED_SSS, 0, 3, _player->GetName(), name, arenaTeam->GetName()); -} - -void WorldSession::SendArenaTeamCommandResult(uint32 teamAction, const std::string& team, const std::string& player, uint32 errorId) -{ - WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4); - data << uint32(teamAction); - data << team; - data << player; - data << uint32(errorId); - SendPacket(&data); -} - -void WorldSession::SendNotInArenaTeamPacket(uint8 type) -{ - WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team - uint32 unk = 0; - data << uint32(unk); // unk(0) - if (!unk) - data << uint8(type); // team type (2=2v2, 3=3v3, 5=5v5), can be used for custom types... - SendPacket(&data); -} - -/* -+ERR_ARENA_NO_TEAM_II "You are not in a %dv%d arena team" - -+ERR_ARENA_TEAM_CREATE_S "%s created. To disband, use /teamdisband [2v2, 3v3, 5v5]." -+ERR_ARENA_TEAM_INVITE_SS "You have invited %s to join %s" -+ERR_ARENA_TEAM_QUIT_S "You are no longer a member of %s" -ERR_ARENA_TEAM_FOUNDER_S "Congratulations, you are a founding member of %s! To leave, use /teamquit [2v2, 3v3, 5v5]." - -+ERR_ARENA_TEAM_INTERNAL "Internal arena team error" -+ERR_ALREADY_IN_ARENA_TEAM "You are already in an arena team of that size" -+ERR_ALREADY_IN_ARENA_TEAM_S "%s is already in an arena team of that size" -+ERR_INVITED_TO_ARENA_TEAM "You have already been invited into an arena team" -+ERR_ALREADY_INVITED_TO_ARENA_TEAM_S "%s has already been invited to an arena team" -+ERR_ARENA_TEAM_NAME_INVALID "That name contains invalid characters, please enter a new name" -+ERR_ARENA_TEAM_NAME_EXISTS_S "There is already an arena team named \"%s\"" -+ERR_ARENA_TEAM_LEADER_LEAVE_S "You must promote a new team captain using /teamcaptain before leaving the team" -+ERR_ARENA_TEAM_PERMISSIONS "You don't have permission to do that" -+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM "You are not in an arena team of that size" -+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS "%s is not in %s" -+ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S "\"%s\" not found" -+ERR_ARENA_TEAM_NOT_ALLIED "You cannot invite players from the opposing alliance" - -+ERR_ARENA_TEAM_JOIN_SS "%s has joined %s" -+ERR_ARENA_TEAM_YOU_JOIN_S "You have joined %s. To leave, use /teamquit [2v2, 3v3, 5v5]." - -+ERR_ARENA_TEAM_LEAVE_SS "%s has left %s" - -+ERR_ARENA_TEAM_LEADER_IS_SS "%s is the captain of %s" -+ERR_ARENA_TEAM_LEADER_CHANGED_SSS "%s has made %s the new captain of %s" - -+ERR_ARENA_TEAM_REMOVE_SSS "%s has been kicked out of %s by %s" - -+ERR_ARENA_TEAM_DISBANDED_S "%s has disbanded %s" - -ERR_ARENA_TEAM_TARGET_TOO_LOW_S "%s is not high enough level to join your team" - -ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full" - -ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team" -*/ diff --git a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp deleted file mode 100755 index 845f3279356..00000000000 --- a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/* - * 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 "ObjectMgr.h" -#include "Player.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" - -#include "AuctionHouseMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "UpdateMask.h" -#include "Util.h" -#include "AccountMgr.h" - -//please DO NOT use iterator++, because it is slower than ++iterator!!! -//post-incrementation is always slower than pre-incrementation ! - -//void called when player click on auctioneer npc -void WorldSession::HandleAuctionHelloOpcode(WorldPacket & recv_data) -{ - uint64 guid; //NPC guid - recv_data >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendAuctionHello(guid, unit); -} - -//this void causes that auction window is opened -void WorldSession::SendAuctionHello(uint64 guid, Creature* unit) -{ - if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_AUCTION_REQ), sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ)); - return; - } - - AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->getFaction()); - if (!ahEntry) - return; - - WorldPacket data(MSG_AUCTION_HELLO, 12); - data << uint64(guid); - data << uint32(ahEntry->houseId); - data << uint8(1); // 3.3.3: 1 - AH enabled, 0 - AH disabled - SendPacket(&data); -} - -//call this method when player bids, creates, or deletes auction -void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError) -{ - WorldPacket data(SMSG_AUCTION_COMMAND_RESULT, 16); - data << auctionId; - data << Action; - data << ErrorCode; - if (!ErrorCode && Action) - data << bidError; //when bid, then send 0, once... - SendPacket(&data); -} - -//this function sends notification, if bidder is online -void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template) -{ - WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4)); - data << uint32(location); - data << uint32(auctionId); - data << uint64(bidder); - data << uint64(bidSum); - data << uint64(diff); - data << uint32(item_template); - data << uint32(0); - SendPacket(&data); -} - -// this void causes on client to display: "Your auction sold" -void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction) -{ - WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, 40); - data << uint32(auction->Id); - data << uint64(auction->bid); - data << uint64(0); //unk - data << uint64(0); //unk - data << uint32(auction->item_template); - data << uint32(0); //unk - data << float(0); //unk - SendPacket(&data); -} - -//this void creates new auction and adds auction to some auctionhouse -void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_SELL_ITEM"); - - uint64 auctioneer, item; - uint32 etime, bid, buyout, count; - recv_data >> auctioneer; - recv_data.read_skip<uint32>(); // const 1? - recv_data >> item; - recv_data >> count; // 3.2.2, number of items being auctioned - recv_data >> bid; - recv_data >> buyout; - recv_data >> etime; - - Player* player = GetPlayer(); - - if (!item || !bid || !etime) - return; //check for cheaters - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); - return; - } - - AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction()); - if (!auctionHouseEntry) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); - return; - } - - // client send time in minutes, convert to common used sec time - etime *= MINUTE; - - // client understand only 3 auction time - switch (etime) - { - case 1*MIN_AUCTION_TIME: - case 2*MIN_AUCTION_TIME: - case 4*MIN_AUCTION_TIME: - break; - default: - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Item* it = player->GetItemByGuid(item); - //do not allow to sell already auctioned items - if (sAuctionMgr->GetAItem(GUID_LOPART(item))) - { - sLog->outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", player->GetName(), GUID_LOPART(item)); - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) - if (!it) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); - return; - } - - if (!it->CanBeTraded()) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - - if (it->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || it->GetUInt32Value(ITEM_FIELD_DURATION)) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - - if (it->IsNotEmptyBag()) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - - //we have to take deposit : - uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, it, count); - if (!player->HasEnoughMoney(deposit)) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); - return; - } - - if (AccountMgr::IsGMAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", - GetPlayerName(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), count); - } - - player->ModifyMoney(-int32(deposit)); - - uint32 auction_time = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); - - AuctionEntry* AH = new AuctionEntry; - AH->Id = sObjectMgr->GenerateAuctionID(); - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - AH->auctioneer = 23442; - else - AH->auctioneer = GUID_LOPART(auctioneer); - AH->item_guidlow = GUID_LOPART(item); - AH->item_template = it->GetEntry(); - AH->owner = player->GetGUIDLow(); - AH->startbid = bid; - AH->bidder = 0; - AH->bid = 0; - AH->buyout = buyout; - AH->expire_time = time(NULL) + auction_time; - AH->deposit = deposit; - AH->auctionHouseEntry = auctionHouseEntry; - - sLog->outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); - sAuctionMgr->AddAItem(it); - auctionHouse->AddAuction(AH); - - player->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - it->DeleteFromInventoryDB(trans); - it->SaveToDB(trans); // recursive and not have transaction guard into self, not in inventiory and can be save standalone - AH->SaveToDB(trans); - player->SaveInventoryAndGoldToDB(trans); - CharacterDatabase.CommitTransaction(trans); - - SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); - - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); -} - -// this function is called when client bids or buys out auction -void WorldSession::HandleAuctionPlaceBid(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID"); - - uint64 auctioneer; - uint32 auctionId; - uint64 price; - recv_data >> auctioneer; - recv_data >> auctionId; - recv_data >> price; - - if (!auctionId || !price) - return; // check for cheaters - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - - AuctionEntry* auction = auctionHouse->GetAuction(auctionId); - Player* player = GetPlayer(); - - if (!auction || auction->owner == player->GetGUIDLow()) - { - //you cannot bid your own auction: - SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); - return; - } - - // impossible have online own another character (use this for speedup check in case online owner) - Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); - if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == player->GetSession()->GetAccountId()) - { - //you cannot bid your another character auction: - SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); - return; - } - - // cheating - if (price <= auction->bid || price < auction->startbid) - return; - - // price too low for next bid if not buyout - if ((price < auction->buyout || auction->buyout == 0) && - price < auction->bid + auction->GetAuctionOutBid()) - { - //auction has already higher bid, client tests it! - return; - } - - if (!player->HasEnoughMoney((uint32)price)) - { - //you don't have enought money!, client tests! - //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); - return; - } - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - - if (price < auction->buyout || auction->buyout == 0) - { - if (auction->bidder > 0) - { - if (auction->bidder == player->GetGUIDLow()) - player->ModifyMoney(-int32(price - auction->bid)); - else - { - // mail to last bidder and return money - sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans); - player->ModifyMoney(-int32(price)); - } - } - else - player->ModifyMoney(-int32(price)); - - auction->bidder = player->GetGUIDLow(); - auction->bid = price; - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); - - trans->PAppend("UPDATE auctionhouse SET buyguid = '%u', lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); - - SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0); - } - else - { - //buyout: - if (player->GetGUIDLow() == auction->bidder) - player->ModifyMoney(-int32(auction->buyout - auction->bid)); - else - { - player->ModifyMoney(-int32(auction->buyout)); - if (auction->bidder) //buyout for bidded auction .. - sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); - } - auction->bidder = player->GetGUIDLow(); - auction->bid = auction->buyout; - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); - - //- Mails must be under transaction control too to prevent data loss - sAuctionMgr->SendAuctionSalePendingMail(auction, trans); - sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); - sAuctionMgr->SendAuctionWonMail(auction, trans); - - SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); - - auction->DeleteFromDB(trans); - - uint32 item_template = auction->item_template; - sAuctionMgr->RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); - } - player->SaveInventoryAndGoldToDB(trans); - CharacterDatabase.CommitTransaction(trans); -} - -//this void is called when auction_owner cancels his auction -void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_REMOVE_ITEM"); - - uint64 auctioneer; - uint32 auctionId; - recv_data >> auctioneer; - recv_data >> auctionId; - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - - AuctionEntry* auction = auctionHouse->GetAuction(auctionId); - Player* player = GetPlayer(); - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - if (auction && auction->owner == player->GetGUIDLow()) - { - Item* pItem = sAuctionMgr->GetAItem(auction->item_guidlow); - if (pItem) - { - if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid - { - uint32 auctionCut = auction->GetAuctionCut(); - if (!player->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed - return; - //some auctionBidderNotification would be needed, but don't know that parts.. - sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans); - player->ModifyMoney(-int32(auctionCut)); - } - // Return the item by mail - std::ostringstream msgAuctionCanceledOwner; - msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED << ":0:0"; - - // item will deleted or added to received mail list - MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body - .AddItem(pItem) - .SendMailTo(trans, player, auction, MAIL_CHECK_MASK_COPIED); - } - else - { - sLog->outError("Auction id: %u got non existing item (item guid : %u)!", auction->Id, auction->item_guidlow); - SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); - return; - } - } - else - { - SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); - //this code isn't possible ... maybe there should be assert - sLog->outError("CHEATER: %u tried to cancel auction (id: %u) of another player or auction is NULL", player->GetGUIDLow(), auctionId); - return; - } - - //inform player, that auction is removed - SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, AUCTION_OK); - - // Now remove the auction - - player->SaveInventoryAndGoldToDB(trans); - auction->DeleteFromDB(trans); - CharacterDatabase.CommitTransaction(trans); - - uint32 item_template = auction->item_template; - sAuctionMgr->RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); -} - -//called when player lists his bids -void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_BIDDER_ITEMS"); - - uint64 guid; //NPC guid - uint32 listfrom; //page of auctions - uint32 outbiddedCount; //count of outbidded auctions - - recv_data >> guid; - recv_data >> listfrom; // not used in fact (this list not have page control in client) - recv_data >> outbiddedCount; - if (recv_data.size() != (16 + outbiddedCount * 4)) - { - sLog->outError("Client sent bad opcode!!! with count: %u and size : %lu (must be: %u)", outbiddedCount, (unsigned long)recv_data.size(), (16 + outbiddedCount * 4)); - outbiddedCount = 0; - } - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - recv_data.rfinish(); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - - WorldPacket data(SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4)); - Player* player = GetPlayer(); - data << uint32(0); //add 0 as count - uint32 count = 0; - uint32 totalcount = 0; - while (outbiddedCount > 0) //add all data, which client requires - { - --outbiddedCount; - uint32 outbiddedAuctionId; - recv_data >> outbiddedAuctionId; - AuctionEntry* auction = auctionHouse->GetAuction(outbiddedAuctionId); - if (auction && auction->BuildAuctionInfo(data)) - { - ++totalcount; - ++count; - } - } - - auctionHouse->BuildListBidderItems(data, player, count, totalcount); - data.put<uint32>(0, count); // add count to placeholder - data << totalcount; - data << uint32(300); //unk 2.3.0 - SendPacket(&data); -} - -//this void sends player info about his auctions -void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS"); - - uint32 listfrom; - uint64 guid; - - recv_data >> guid; - recv_data >> listfrom; // not used in fact (this list not have page control in client) - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionListOwnerItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - - WorldPacket data(SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4)); - data << uint32(0); // amount place holder - - uint32 count = 0; - uint32 totalcount = 0; - - auctionHouse->BuildListOwnerItems(data, _player, count, totalcount); - data.put<uint32>(0, count); - data << uint32(totalcount); - data << uint32(0); - SendPacket(&data); -} - -//this void is called when player clicks on search button -void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_ITEMS"); - - std::string searchedname; - uint8 levelmin, levelmax, usable; - uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; - uint64 guid; - - recv_data >> guid; - recv_data >> listfrom; // start, used for page control listing by 50 elements - recv_data >> searchedname; - - recv_data >> levelmin >> levelmax; - recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; - recv_data >> quality >> usable; - - recv_data.read_skip<uint8>(); // unk - - // this block looks like it uses some lame byte packing or similar... - uint8 unkCnt; - recv_data >> unkCnt; - for (uint8 i = 0; i < unkCnt; i++) - { - recv_data.read_skip<uint8>(); - recv_data.read_skip<uint8>(); - } - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_AUCTIONEER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionListItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); - - //sLog->outDebug("Auctionhouse search (GUID: %u TypeId: %u)",, list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u", - // GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)), listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable); - - WorldPacket data(SMSG_AUCTION_LIST_RESULT, (4+4+4)); - uint32 count = 0; - uint32 totalcount = 0; - data << (uint32) 0; - - // converting string that we try to find to lower case - std::wstring wsearchedname; - if (!Utf8toWStr(searchedname, wsearchedname)) - return; - - wstrToLower(wsearchedname); - - auctionHouse->BuildListAuctionItems(data, _player, - wsearchedname, listfrom, levelmin, levelmax, usable, - auctionSlotID, auctionMainCategory, auctionSubCategory, quality, - count, totalcount); - - data.put<uint32>(0, count); - data << uint32(totalcount); - data << uint32(300); //unk 2.3.0 - SendPacket(&data); -} - -void WorldSession::HandleAuctionListPendingSales(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_LIST_PENDING_SALES"); - - recv_data.read_skip<uint64>(); - - uint32 count = 0; - - WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4); - data << uint32(count); // count - /*for (uint32 i = 0; i < count; ++i) - { - data << ""; // string - data << ""; // string - data << uint32(0); - data << uint32(0); - data << float(0); - }*/ - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/AuthHandler.cpp b/src/server/game/Server/Protocol/Handlers/AuthHandler.cpp deleted file mode 100755 index c5dbcb4f946..00000000000 --- a/src/server/game/Server/Protocol/Handlers/AuthHandler.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * - * 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 "Opcodes.h" -#include "WorldSession.h" -#include "WorldPacket.h" - -void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) -{ - WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + (shortForm ? 0 : (4 + 1))); - packet << uint8(code); - packet << uint32(0); // BillingTimeRemaining - packet << uint8(0); // BillingPlanFlags - packet << uint32(0); // BillingTimeRested - packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account - packet << uint8(Expansion()); // Unknown, these two show the same - - if (!shortForm) - { - packet << uint32(queuePos); // Queue position - packet << uint8(0); // Unk 3.3.0 - } - - SendPacket(&packet); -} - -void WorldSession::SendClientCacheVersion(uint32 version) -{ - WorldPacket data(SMSG_CLIENTCACHE_VERSION, 4); - data << uint32(version); - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp deleted file mode 100755 index 00f18217eed..00000000000 --- a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp +++ /dev/null @@ -1,784 +0,0 @@ -/* - * 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; - } - - SendBattlegGroundList(guid, bgTypeId); -} - -void WorldSession::SendBattlegGroundList(uint64 guid, BattlegroundTypeId bgTypeId) -{ - WorldPacket data; - sBattlegroundMgr->BuildBattlegroundListPacket(&data, guid, _player, bgTypeId); - 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("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 - - 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)); - 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("BattlegroundHandler: itrplayerstatus not found."); - return; - } - // if action == 1, then instanceId is required - if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) - { - sLog->outError("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("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("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("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("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); - return; - } - - //check existance - Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); - if (!bg) - { - sLog->outError("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); -} diff --git a/src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp b/src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp deleted file mode 100755 index be547c84b19..00000000000 --- a/src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" - -#include "InstanceSaveMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" - -void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recv_data*/) -{ - uint64 guid = _player->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_CALENDAR_GET_CALENDAR [" UI64FMTD "]", guid); - - time_t cur_time = time_t(time(NULL)); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_CALENDAR_SEND_CALENDAR [" UI64FMTD "]", guid); - WorldPacket data(SMSG_CALENDAR_SEND_CALENDAR, 4+4*0+4+4*0+4+4); - - data << uint32(0); // invite count - /* - for (;;) - { - uint64 inviteId; - uint64 unkGuid0; - uint8 unk1, unk2, unk3; - uint64 creatorGuid; - } - */ - - data << uint32(0); // event count - /* - for (;;) - { - uint64 eventId; - std::string title; // 128 chars - uint32 type; - uint32 occurrenceTime; - uint32 flags; - uint32 unk4; -- possibly mapid for dungeon/raid - uint64 creatorGuid; - } - */ - - data << uint32(cur_time); // server time - data << uint32(secsToTimeBitFields(cur_time)); // server time - - uint32 counter = 0; - size_t p_counter = data.wpos(); - data << uint32(counter); // instance save count - - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - for (Player::BoundInstancesMap::const_iterator itr = _player->m_boundInstances[i].begin(); itr != _player->m_boundInstances[i].end(); ++itr) - if (itr->second.perm) - { - InstanceSave const* save = itr->second.save; - data << uint32(save->GetMapId()); - data << uint32(save->GetDifficulty()); - data << uint32(save->GetResetTime() - cur_time); - data << uint64(save->GetInstanceId()); // instance save id as unique instance copy id - ++counter; - } - - data.put<uint32>(p_counter, counter); - - data << uint32(1135753200); // unk (28.12.2005 07:00) - - counter = 0; - p_counter = data.wpos(); - data << uint32(counter); // raid reset count - - std::set<uint32> sentMaps; - - ResetTimeByMapDifficultyMap const& resets = sInstanceSaveMgr->GetResetTimeMap(); - for (ResetTimeByMapDifficultyMap::const_iterator itr = resets.begin(); itr != resets.end(); ++itr) - { - uint32 mapId = PAIR32_LOPART(itr->first); - - if (sentMaps.find(mapId) != sentMaps.end()) - continue; - - MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); - if (!mapEntry || !mapEntry->IsRaid()) - continue; - - sentMaps.insert(mapId); - - data << uint32(mapId); - data << uint32(itr->second - cur_time); - data << uint32(mapEntry->unk_time); - ++counter; - } - - data.put<uint32>(p_counter, counter); - - data << uint32(0); // holiday count? - /* - for (;;) - { - uint32 unk5, unk6, unk7, unk8, unk9; - for (uint32 j = 0; j < 26; ++j) - { - uint32 unk10; - } - for (uint32 j = 0; j < 10; ++j) - { - uint32 unk11; - } - for (uint32 j = 0; j < 10; ++j) - { - uint32 unk12; - } - std::string holidayName; // 64 chars - } - */ - - SendPacket(&data); -} - -void WorldSession::HandleCalendarGetEvent(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_GET_EVENT"); - recv_data.read_skip<uint64>(); // unk -} - -void WorldSession::HandleCalendarGuildFilter(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_GUILD_FILTER"); - recv_data.read_skip<uint32>(); // unk1 - recv_data.read_skip<uint32>(); // unk2 - recv_data.read_skip<uint32>(); // unk3 -} - -void WorldSession::HandleCalendarArenaTeam(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_ARENA_TEAM"); - recv_data.read_skip<uint32>(); // unk -} - -void WorldSession::HandleCalendarAddEvent(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_ADD_EVENT"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //std::string unk1, unk2; - //recv_data >> (std::string)unk1; - //recv_data >> (std::string)unk2; - - //uint8 unk3, unk4; - //uint32 unk5, unk6, unk7, unk8, unk9, count = 0; - //recv_data >> (uint8)unk3; - //recv_data >> (uint8)unk4; - //recv_data >> (uint32)unk5; - //recv_data >> (uint32)unk6; - //recv_data >> (uint32)unk7; - //recv_data >> (uint32)unk8; - //recv_data >> (uint32)unk9; - //if (!((unk9 >> 6) & 1)) - //{ - // recv_data >> (uint32)count; - // if (count) - // { - // uint8 unk12, unk13; - // uint64 guid; - // for (int i=0; i<count; i++) - // { - // recv_data.readPackGUID(guid); - // recv_data >> (uint8)unk12; - // recv_data >> (uint8)unk13; - // } - // } - //} -} - -void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_UPDATE_EVENT"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> std::string - //recv_data >> std::string - //recv_data >> uint8 - //recv_data >> uint8 - //recv_data >> uint32 - //recv_data >> uint32 - //recv_data >> uint32 - //recv_data >> uint32 - //recv_data >> uint32 -} - -void WorldSession::HandleCalendarRemoveEvent(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_REMOVE_EVENT"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 - -} - -void WorldSession::HandleCalendarCopyEvent(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_COPY_EVENT"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 - -} - -void WorldSession::HandleCalendarEventInvite(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_EVENT_INVITE"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> std::string - //recv_data >> uint8 - //recv_data >> uint8 - -} - -void WorldSession::HandleCalendarEventRsvp(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_EVENT_RSVP"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 - -} - -void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data.readPackGUID(guid) - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 -} - -void WorldSession::HandleCalendarEventStatus(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_EVENT_STATUS"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data.readPackGUID(guid) - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 -} - -void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data.readPackGUID(guid) - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 -} - -void WorldSession::HandleCalendarComplain(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_COMPLAIN"); - recv_data.rfinish(); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 -} - -void WorldSession::HandleCalendarGetNumPending(WorldPacket& /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CALENDAR_GET_NUM_PENDING"); // empty - - WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4); - data << uint32(0); // 0 - no pending invites, 1 - some pending invites - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp deleted file mode 100755 index efa2d54a65d..00000000000 --- a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * 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 "ObjectMgr.h" // for normalizePlayerName -#include "ChannelMgr.h" - -void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - - uint32 channelId; - uint8 unknown1, unknown2; - std::string channelName, pass; - - recvPacket >> channelId; - recvPacket >> unknown1 >> unknown2; - recvPacket >> pass; - recvPacket >> channelName; - - if (channelId) - { - ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channelId); - if (!channel) - return; - - AreaTableEntry const* current_zone = GetAreaEntryByAreaID(_player->GetZoneId()); - if (!current_zone) - return; - - if (!_player->CanJoinConstantChannelInZone(channel, current_zone)) - return; - } - - if (channelName.empty()) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - cMgr->team = _player->GetTeam(); - if (Channel* chn = cMgr->GetJoinChannel(channelName, channelId)) - chn->Join(_player->GetGUID(), pass.c_str()); - } -} - -void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - - uint32 unk; - std::string channelname; - recvPacket >> unk; // channel id? - recvPacket >> channelname; - - if (channelname.empty()) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->Leave(_player->GetGUID(), true); - cMgr->LeftChannel(channelname); - } -} - -void WorldSession::HandleChannelList(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->List(_player); -} - -void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, pass; - recvPacket >> channelname; - - recvPacket >> pass; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->Password(_player->GetGUID(), pass.c_str()); -} - -void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, newp; - recvPacket >> channelname; - - recvPacket >> newp; - - if (!normalizePlayerName(newp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->SetOwner(_player->GetGUID(), newp.c_str()); -} - -void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->SendWhoOwner(_player->GetGUID()); -} - -void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->SetModerator(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->UnsetModerator(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelMute(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->SetMute(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->UnsetMute(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->Invite(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelKick(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->Kick(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelBan(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->Ban(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->UnBan(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - chn->Announce(_player->GetGUID()); -} - -void WorldSession::HandleChannelDisplayListQuery(WorldPacket &recvPacket) -{ - // this should be OK because the 2 function _were_ the same - HandleChannelList(recvPacket); -} - -void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - if (Channel* chn = cMgr->GetChannel(channelname, _player)) - { - WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, chn->GetName().size()+1+1+4); - data << chn->GetName(); - data << uint8(chn->GetFlags()); - data << uint32(chn->GetNumPlayers()); - SendPacket(&data); - } - } -} - -void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); - std::string channelname; - recvPacket >> channelname; - /*if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel* chn = cMgr->GetChannel(channelName, _player)) - chn->JoinNotify(_player->GetGUID());*/ -} - diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp deleted file mode 100644 index 62b9fe0b582..00000000000 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ /dev/null @@ -1,2035 +0,0 @@ -/* - * 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 "GuildMgr.h" -#include "SystemConfig.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "DatabaseEnv.h" -#include "ArenaTeam.h" -#include "Chat.h" -#include "Group.h" -#include "Guild.h" -#include "Language.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" -#include "PlayerDump.h" -#include "SharedDefines.h" -#include "SocialMgr.h" -#include "UpdateMask.h" -#include "Util.h" -#include "ScriptMgr.h" -#include "Battleground.h" -#include "AccountMgr.h" -#include "DBCStores.h" - -class LoginQueryHolder : public SQLQueryHolder -{ - private: - uint32 m_accountId; - uint64 m_guid; - public: - LoginQueryHolder(uint32 accountId, uint64 guid) - : m_accountId(accountId), m_guid(guid) { } - uint64 GetGuid() const { return m_guid; } - uint32 GetAccountId() const { return m_accountId; } - bool Initialize(); -}; - -bool LoginQueryHolder::Initialize() -{ - SetSize(MAX_PLAYER_LOGIN_QUERY); - - bool res = true; - uint32 lowGuid = GUID_LOPART(m_guid); - PreparedStatement* stmt = NULL; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADFROM, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADGROUP, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_INSTANCE); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AURAS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADAURAS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELL); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_DAILYQUESTSTATUS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADSEASONALQUESTSTATUS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_REPUTATION); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADREPUTATION, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_INVENTORY); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_MAILCOUNT); - stmt->setUInt32(0, lowGuid); - stmt->setUInt64(1, uint64(time(NULL))); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADMAILCOUNT, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_MAILDATE); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADMAILDATE, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SOCIALLIST); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADSOCIALLIST, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_HOMEBIND); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADHOMEBIND, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS, stmt); - - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED)) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_DECLINEDNAMES); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, stmt); - } - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADGUILD, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ARENAINFO); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACHIEVEMENTS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GLYPHS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADGLYPHS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TALENTS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADTALENTS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_ACCOUNT_DATA); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SKILLS); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_RANDOMBG); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADRANDOMBG, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BANNED); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADBANNED, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW); - stmt->setUInt32(0, lowGuid); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUSREW, stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES); - stmt->setUInt32(0, m_accountId); - res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOADINSTANCELOCKTIMES, stmt); - - return res; -} - -void WorldSession::HandleCharEnum(PreparedQueryResult result) -{ - WorldPacket data(SMSG_CHAR_ENUM, 270); - - data << uint8(0x80); // 0 causes the client to free memory of charlist - data << uint32(0); // number of characters - data << uint32(0); // unk loop counter - - if (result) - { - typedef std::pair<uint32, uint64> Guids; - std::vector<Guids> guidsVect; - ByteBuffer buffer; - _allowedCharsToLogin.clear(); - - do - { - uint32 GuidLow = (*result)[0].GetUInt32(); - uint64 GuildGuid = (*result)[13].GetUInt32();//TODO: store as uin64 - - guidsVect.push_back(std::make_pair(GuidLow, GuildGuid)); - - sLog->outDetail("Loading char guid %u from account %u.", GuidLow, GetAccountId()); - - if (!Player::BuildEnumData(result, &buffer)) - { - sLog->outError("Building enum data for SMSG_CHAR_ENUM has failed, aborting"); - return; - } - _allowedCharsToLogin.insert(GuidLow); - } - while (result->NextRow()); - - for (std::vector<Guids>::iterator itr = guidsVect.begin(); itr != guidsVect.end(); ++itr) - { - uint32 GuidLow = (*itr).first; - uint64 GuildGuid = (*itr).second; - - uint8 Guid0 = uint8(GuidLow); - uint8 Guid1 = uint8(GuidLow >> 8); - uint8 Guid2 = uint8(GuidLow >> 16); - uint8 Guid3 = uint8(GuidLow >> 24); - - for (uint8 i = 0; i < 17; ++i) - { - switch(i) - { - //case 14: - // data.writeBit(1);//unk - // break; - case 11: data.WriteBit(Guid0 ? 1 : 0); break; - case 12: data.WriteBit(Guid1 ? 1 : 0); break; - case 9: data.WriteBit(Guid2 ? 1 : 0); break; - case 8: data.WriteBit(Guid3 ? 1 : 0); break; - /*case 15: - if(uint8(GuildGuid)) - data.writeBit(1); - break; - case 4: - if(uint8(GuildGuid >> 8)) - data.writeBit(1); - break; - case 13: - if(uint8(GuildGuid >> 16)) - data.writeBit(1); - break; - case 2: - if(uint8(GuildGuid >> 24)) - data.writeBit(1); - break;*/ - /*case 0: - if(uint8(GuildGuid >> 32)) - data.writeBit(1); - break; - case 0: - if(uint8(GuildGuid >> 40)) - data.writeBit(1); - break;*/ - /*case 5: - if(uint8(GuildGuid >> 48)) - data.writeBit(1); - break; - case 3: - if(uint8(GuildGuid >> 56)) - data.writeBit(1); - break;*/ - default: - data.WriteBit(0); - break; - } - } - } - data.FlushBits(); - data.append(buffer); - data.put<uint32>(1, guidsVect.size()); - } - - SendPacket(&data); -} - -void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) -{ - // remove expired bans - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_BANS); - CharacterDatabase.Execute(stmt); - - /// get all the data necessary for loading all characters (along with their pets) on the account - - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED)) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM_DECLINED_NAME); - else - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM); - - stmt->setUInt8(0, PET_SAVE_AS_CURRENT); - stmt->setUInt32(1, GetAccountId()); - - _charEnumCallback = CharacterDatabase.AsyncQuery(stmt); -} - -void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) -{ - std::string name; - uint8 race_, class_; - - recv_data >> name; - - recv_data >> race_; - recv_data >> class_; - - // extract other data required for player creating - uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; - recv_data >> gender >> skin >> face; - recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; - - WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases - - if (AccountMgr::IsPlayerAccount(GetSecurity())) - { - if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED)) - { - bool disabled = false; - - uint32 team = Player::TeamForRace(race_); - switch (team) - { - case ALLIANCE: disabled = mask & (1 << 0); break; - case HORDE: disabled = mask & (1 << 1); break; - } - - if (disabled) - { - data << (uint8)CHAR_CREATE_DISABLED; - SendPacket(&data); - return; - } - } - } - - ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); - if (!classEntry) - { - data << (uint8)CHAR_CREATE_FAILED; - SendPacket(&data); - sLog->outError("Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", class_, GetAccountId()); - return; - } - - ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); - if (!raceEntry) - { - data << (uint8)CHAR_CREATE_FAILED; - SendPacket(&data); - sLog->outError("Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", race_, GetAccountId()); - return; - } - - // prevent character creating Expansion race without Expansion account - if (raceEntry->expansion > Expansion()) - { - data << (uint8)CHAR_CREATE_EXPANSION; - sLog->outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, race_); - SendPacket(&data); - return; - } - - // prevent character creating Expansion class without Expansion account - if (classEntry->expansion > Expansion()) - { - data << (uint8)CHAR_CREATE_EXPANSION_CLASS; - sLog->outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, class_); - SendPacket(&data); - return; - } - - if (AccountMgr::IsPlayerAccount(GetSecurity())) - { - uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK); - if ((1 << (race_ - 1)) & raceMaskDisabled) - { - data << uint8(CHAR_CREATE_DISABLED); - SendPacket(&data); - return; - } - - uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK); - if ((1 << (class_ - 1)) & classMaskDisabled) - { - data << uint8(CHAR_CREATE_DISABLED); - SendPacket(&data); - return; - } - } - - // prevent character creating with invalid name - if (!normalizePlayerName(name)) - { - data << (uint8)CHAR_NAME_NO_NAME; - SendPacket(&data); - sLog->outError("Account:[%d] but tried to Create character with empty [name] ", GetAccountId()); - return; - } - - // check name limitations - uint8 res = ObjectMgr::CheckPlayerName(name, true); - if (res != CHAR_NAME_SUCCESS) - { - data << uint8(res); - SendPacket(&data); - return; - } - - if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(name)) - { - data << (uint8)CHAR_NAME_RESERVED; - SendPacket(&data); - return; - } - - // speedup check for heroic class disabled case - uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); - if (heroic_free_slots == 0 && AccountMgr::IsPlayerAccount(GetSecurity()) && class_ == CLASS_DEATH_KNIGHT) - { - data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; - SendPacket(&data); - return; - } - - // speedup check for heroic class disabled case - uint32 req_level_for_heroic = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER); - if (AccountMgr::IsPlayerAccount(GetSecurity()) && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; - SendPacket(&data); - return; - } - - delete _charCreateCallback.GetParam(); // Delete existing if any, to make the callback chain reset to stage 0 - _charCreateCallback.SetParam(new CharacterCreateInfo(name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId, recv_data)); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); - stmt->setString(0, name); - _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); -} - -void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo) -{ - /** This is a series of callbacks executed consecutively as a result from the database becomes available. - This is much more efficient than synchronous requests on packet handler, and much less DoS prone. - It also prevents data syncrhonisation errors. - */ - switch (_charCreateCallback.GetStage()) - { - case 0: - { - if (result) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_NAME_IN_USE); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - - ASSERT(_charCreateCallback.GetParam() == createInfo); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS); - stmt->setUInt32(0, GetAccountId()); - - _charCreateCallback.FreeResult(); - _charCreateCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt)); - _charCreateCallback.NextStage(); - } - break; - case 1: - { - uint16 acctCharCount = 0; - if (result) - { - Field* fields = result->Fetch(); - // SELECT SUM(x) is MYSQL_TYPE_NEWDECIMAL - needs to be read as string - const char* ch = fields[0].GetCString(); - if (ch) - acctCharCount = atoi(ch); - } - - if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_ACCOUNT_LIMIT); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - - - ASSERT(_charCreateCallback.GetParam() == createInfo); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS); - stmt->setUInt32(0, GetAccountId()); - - _charCreateCallback.FreeResult(); - _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); - _charCreateCallback.NextStage(); - } - break; - case 2: - { - if (result) - { - Field* fields = result->Fetch(); - createInfo->CharCount = fields[0].GetUInt8(); - - if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_SERVER_LIMIT); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - } - - bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity()); - uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS); - - _charCreateCallback.FreeResult(); - - if (!allowTwoSideAccounts || skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) - { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO); - stmt->setUInt32(0, GetAccountId()); - stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1); - _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); - _charCreateCallback.NextStage(); - return; - } - - _charCreateCallback.NextStage(); - HandleCharCreateCallback(PreparedQueryResult(NULL), createInfo); // Will jump to case 3 - } - break; - case 3: - { - bool haveSameRace = false; - uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER); - bool hasHeroicReqLevel = (heroicReqLevel == 0); - bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity()); - uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS); - - if (result) - { - uint32 team = Player::TeamForRace(createInfo->Race); - uint32 freeHeroicSlots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); - - Field* field = result->Fetch(); - uint8 accRace = field[1].GetUInt8(); - - if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT) - { - uint8 accClass = field[2].GetUInt8(); - if (accClass == CLASS_DEATH_KNIGHT) - { - if (freeHeroicSlots > 0) - --freeHeroicSlots; - - if (freeHeroicSlots == 0) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_UNIQUE_CLASS_LIMIT); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - } - - if (!hasHeroicReqLevel) - { - uint8 accLevel = field[0].GetUInt8(); - if (accLevel >= heroicReqLevel) - hasHeroicReqLevel = true; - } - } - - // need to check team only for first character - // TODO: what to if account already has characters of both races? - if (!allowTwoSideAccounts) - { - uint32 accTeam = 0; - if (accRace > 0) - accTeam = Player::TeamForRace(accRace); - - if (accTeam != team) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_PVP_TEAMS_VIOLATION); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - } - - // search same race for cinematic or same class if need - // TODO: check if cinematic already shown? (already logged in?; cinematic field) - while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT) - { - if (!result->NextRow()) - break; - - field = result->Fetch(); - accRace = field[1].GetUInt8(); - - if (!haveSameRace) - haveSameRace = createInfo->Race == accRace; - - if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT) - { - uint8 acc_class = field[2].GetUInt8(); - if (acc_class == CLASS_DEATH_KNIGHT) - { - if (freeHeroicSlots > 0) - --freeHeroicSlots; - - if (freeHeroicSlots == 0) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_UNIQUE_CLASS_LIMIT); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - } - - if (!hasHeroicReqLevel) - { - uint8 acc_level = field[0].GetUInt8(); - if (acc_level >= heroicReqLevel) - hasHeroicReqLevel = true; - } - } - } - } - - if (AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT && !hasHeroicReqLevel) - { - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - - if (createInfo->Data.rpos() < createInfo->Data.wpos()) - { - uint8 unk; - createInfo->Data >> unk; - sLog->outDebug(LOG_FILTER_NETWORKIO, "Character creation %s (account %u) has unhandled tail data: [%u]", createInfo->Name.c_str(), GetAccountId(), unk); - } - - Player newChar(this); - if (!newChar.Create(sObjectMgr->GenerateLowGuid(HIGHGUID_PLAYER), createInfo)) - { - // Player not create (race/class/etc problem?) - newChar.CleanupsBeforeDelete(); - - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - delete createInfo; - _charCreateCallback.Reset(); - return; - } - - if ((haveSameRace && skipCinematics == 1) || skipCinematics == 2) - newChar.setCinematic(1); // not show intro - - newChar.SetAtLoginFlag(AT_LOGIN_FIRST); // First login - - // Player created, save it now - newChar.SaveToDB(true); - createInfo->CharCount += 1; - - SQLTransaction trans = LoginDatabase.BeginTransaction(); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS); - stmt->setUInt32(0, GetAccountId()); - stmt->setUInt32(1, realmID); - trans->Append(stmt); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS); - stmt->setUInt32(0, createInfo->CharCount); - stmt->setUInt32(1, GetAccountId()); - stmt->setUInt32(2, realmID); - trans->Append(stmt); - - LoginDatabase.CommitTransaction(trans); - - newChar.CleanupsBeforeDelete(); - - WorldPacket data(SMSG_CHAR_CREATE, 1); - data << uint8(CHAR_CREATE_SUCCESS); - SendPacket(&data); - - std::string IP_str = GetRemoteAddress(); - sLog->outDetail("Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow()); - sLog->outChar("Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow()); - sScriptMgr->OnPlayerCreate(&newChar); - sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass()); - - delete createInfo; - _charCreateCallback.Reset(); - } - break; - } -} - -void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - // can't delete loaded character - if (ObjectAccessor::FindPlayer(guid)) - return; - - uint32 accountId = 0; - std::string name; - - // is guild leader - if (sGuildMgr->GetGuildByLeader(guid)) - { - WorldPacket data(SMSG_CHAR_DELETE, 1); - data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER; - SendPacket(&data); - return; - } - - // is arena team captain - if (sArenaTeamMgr->GetArenaTeamByCaptain(guid)) - { - WorldPacket data(SMSG_CHAR_DELETE, 1); - data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN; - SendPacket(&data); - return; - } - - QueryResult result = CharacterDatabase.PQuery("SELECT account, name FROM characters WHERE guid='%u'", GUID_LOPART(guid)); - if (result) - { - Field* fields = result->Fetch(); - accountId = fields[0].GetUInt32(); - name = fields[1].GetString(); - } - - // prevent deleting other players' characters using cheating tools - if (accountId != GetAccountId()) - return; - - std::string IP_str = GetRemoteAddress(); - sLog->outDetail("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid)); - sLog->outChar("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid)); - sScriptMgr->OnPlayerDelete(guid); - sWorld->DeleteCharaceterNameData(GUID_LOPART(guid)); - - if (sLog->IsOutCharDump()) // optimize GetPlayerDump call - { - std::string dump; - if (PlayerDumpWriter().GetDump(GUID_LOPART(guid), dump)) - sLog->outCharDump(dump.c_str(), GetAccountId(), GUID_LOPART(guid), name.c_str()); - } - - Player::DeleteFromDB(guid, GetAccountId()); - - WorldPacket data(SMSG_CHAR_DELETE, 1); - data << (uint8)CHAR_DELETE_SUCCESS; - SendPacket(&data); -} - -void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data) -{ - if (PlayerLoading() || GetPlayer() != NULL) - { - sLog->outError("Player tryes to login again, AccountId = %d", GetAccountId()); - return; - } - - m_playerLoading = true; - uint64 playerGuid = 0; - - sLog->outStaticDebug("WORLD: Recvd Player Logon Message"); - - BitStream mask = recv_data.ReadBitStream(8); - - ByteBuffer bytes(8, true); - - recv_data.ReadXorByte(mask[6], bytes[5]); - recv_data.ReadXorByte(mask[0], bytes[0]); - recv_data.ReadXorByte(mask[4], bytes[3]); - recv_data.ReadXorByte(mask[1], bytes[4]); - recv_data.ReadXorByte(mask[2], bytes[7]); - recv_data.ReadXorByte(mask[5], bytes[2]); - recv_data.ReadXorByte(mask[7], bytes[6]); - recv_data.ReadXorByte(mask[3], bytes[1]); - - playerGuid = BitConverter::ToUInt64(bytes); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Character (Guid: %u) logging in", GUID_LOPART(playerGuid)); - - if (!CharCanLogin(GUID_LOPART(playerGuid))) - { - sLog->outError("Account (%u) can't login with that character (%u).", GetAccountId(), GUID_LOPART(playerGuid)); - KickPlayer(); - return; - } - - LoginQueryHolder *holder = new LoginQueryHolder(GetAccountId(), playerGuid); - if (!holder->Initialize()) - { - delete holder; // delete all unprocessed queries - m_playerLoading = false; - return; - } - - _charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); -} - -void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket) -{ - sLog->outStaticDebug("WORLD: Recvd CMSG_LOAD_SCREEN"); - uint8 unkMask; // Loading start: 0x80, loading end: 0x0 - uint32 mapID; - recvPacket >> unkMask >> mapID; - - // TODO: Do something with this packet -} - -void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) -{ - uint64 playerGuid = holder->GetGuid(); - - Player* pCurrChar = new Player(this); - // for send server info and strings (config) - ChatHandler chH = ChatHandler(pCurrChar); - - // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) - if (!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) - { - KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick - delete pCurrChar; // delete it manually - delete holder; // delete all unprocessed queries - m_playerLoading = false; - return; - } - - pCurrChar->GetMotionMaster()->Initialize(); - - SetPlayer(pCurrChar); - - pCurrChar->SendDungeonDifficulty(false); - - WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); - data << pCurrChar->GetMapId(); - data << pCurrChar->GetPositionX(); - data << pCurrChar->GetPositionY(); - data << pCurrChar->GetPositionZ(); - data << pCurrChar->GetOrientation(); - SendPacket(&data); - - // load player specific part before send times - LoadAccountData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA), PER_CHARACTER_CACHE_MASK); - SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); - - data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 7); // checked in 4.2.2 - data << uint8(2); // unknown value - data << uint8(0); // enable(1)/disable(0) voice chat interface in client - data << uint8(0); - data << uint32(0); // mail related - SendPacket(&data); - - // Send MOTD - { - data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 - data << (uint32)0; - - uint32 linecount=0; - std::string str_motd = sWorld->GetMotd(); - std::string::size_type pos, nextpos; - - pos = 0; - while ((nextpos= str_motd.find('@', pos)) != std::string::npos) - { - if (nextpos != pos) - { - data << str_motd.substr(pos, nextpos-pos); - ++linecount; - } - pos = nextpos+1; - } - - if (pos<str_motd.length()) - { - data << str_motd.substr(pos); - ++linecount; - } - - data.put(0, linecount); - - SendPacket(&data); - sLog->outStaticDebug("WORLD: Sent motd (SMSG_MOTD)"); - - // send server info - if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1) - chH.PSendSysMessage(_FULLVERSION); - - sLog->outStaticDebug("WORLD: Sent server info"); - } - - //QueryResult* result = CharacterDatabase.PQuery("SELECT guildid, rank FROM guild_member WHERE guid = '%u'", pCurrChar->GetGUIDLow()); - if (PreparedQueryResult resultGuild = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADGUILD)) - { - Field* fields = resultGuild->Fetch(); - pCurrChar->SetInGuild(fields[0].GetUInt32()); - pCurrChar->SetRank(fields[1].GetUInt8()); - } - else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership - { - pCurrChar->SetInGuild(0); - pCurrChar->SetRank(0); - } - - if (pCurrChar->GetGuildId() != 0) - { - if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId())) - guild->SendLoginInfo(this); - else - { - // remove wrong guild data - sLog->outError("Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.", pCurrChar->GetName(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId()); - pCurrChar->SetInGuild(0); - } - } - - data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); - data << uint32(0); - data << uint32(0); - SendPacket(&data); - - pCurrChar->SendInitialPacketsBeforeAddToMap(); - - //Show cinematic at the first time that player login - if (!pCurrChar->getCinematic()) - { - pCurrChar->setCinematic(1); - - if (ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) - { - if (cEntry->CinematicSequence) - pCurrChar->SendCinematicStart(cEntry->CinematicSequence); - else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) - pCurrChar->SendCinematicStart(rEntry->CinematicSequence); - - // send new char string if not empty - if (!sWorld->GetNewCharString().empty()) - chH.PSendSysMessage("%s", sWorld->GetNewCharString().c_str()); - } - } - - if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar) || !pCurrChar->CheckInstanceLoginValid()) - { - AreaTrigger const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId()); - if (at) - pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); - else - pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); - } - - sObjectAccessor->AddObject(pCurrChar); - //sLog->outDebug("Player %s added to Map.", pCurrChar->GetName()); - - pCurrChar->SendInitialPacketsAfterAddToMap(); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE); - - stmt->setUInt32(0, pCurrChar->GetGUIDLow()); - - CharacterDatabase.Execute(stmt); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE); - - stmt->setUInt32(0, GetAccountId()); - - LoginDatabase.Execute(stmt); - - pCurrChar->SetInGameTime(getMSTime()); - - // announce group about member online (must be after add to player list to receive announce to self) - if (Group* group = pCurrChar->GetGroup()) - { - //pCurrChar->groupInfo.group->SendInit(this); // useless - group->SendUpdate(); - group->ResetMaxEnchantingLevel(); - } - - // friend status - sSocialMgr->SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); - - // Place character in world (and load zone) before some object loading - pCurrChar->LoadCorpse(); - - // setting Ghost+speed if dead - if (pCurrChar->m_deathState != ALIVE) - { - // not blizz like, we must correctly save and load player instead... - if (pCurrChar->getRace() == RACE_NIGHTELF) - pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) - pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - - pCurrChar->SetMovement(MOVE_WATER_WALK); - } - - pCurrChar->ContinueTaxiFlight(); - - // reset for all pets before pet loading - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) - Pet::resetTalentsForAllPetsOf(pCurrChar); - - // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) - pCurrChar->LoadPet(); - - // Set FFA PvP for non GM in non-rest mode - if (sWorld->IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) - pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - - if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) - pCurrChar->SetContestedPvP(); - - // Apply at_login requests - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) - { - pCurrChar->resetSpells(); - SendNotification(LANG_RESET_SPELLS); - } - - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) - { - pCurrChar->ResetTalents(true); - pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state - SendNotification(LANG_RESET_TALENTS); - } - - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST)) - pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST); - - // show time before shutdown if shutdown planned. - if (sWorld->IsShuttingDown()) - sWorld->ShutdownMsg(true, pCurrChar); - - if (sWorld->getBoolConfig(CONFIG_ALL_TAXI_PATHS)) - pCurrChar->SetTaxiCheater(true); - - if (pCurrChar->isGameMaster()) - SendNotification(LANG_GM_ON); - - std::string IP_str = GetRemoteAddress(); - sLog->outChar("Account: %d (IP: %s) Login Character:[%s] (GUID: %u)", - GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow()); - - if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STAT_STUNNED)) - pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); - - m_playerLoading = false; - - sScriptMgr->OnPlayerLogin(pCurrChar); - delete holder; -} - -void WorldSession::HandleSetFactionAtWar(WorldPacket & recv_data) -{ - sLog->outStaticDebug("WORLD: Received CMSG_SET_FACTION_ATWAR"); - - uint32 repListID; - uint8 flag; - - recv_data >> repListID; - recv_data >> flag; - - GetPlayer()->GetReputationMgr().SetAtWar(repListID, flag); -} - -//I think this function is never used :/ I dunno, but i guess this opcode not exists -void WorldSession::HandleSetFactionCheat(WorldPacket & /*recv_data*/) -{ - sLog->outError("WORLD SESSION: HandleSetFactionCheat, not expected call, please report."); - GetPlayer()->GetReputationMgr().SendStates(); -} - -void WorldSession::HandleTutorialFlag(WorldPacket & recv_data) -{ - uint32 data; - recv_data >> data; - - uint8 index = uint8(data / 32); - if (index >= MAX_ACCOUNT_TUTORIAL_VALUES) - return; - - uint32 value = (data % 32); - - uint32 flag = GetTutorialInt(index); - flag |= (1 << value); - SetTutorialInt(index, flag); -} - -void WorldSession::HandleTutorialClear(WorldPacket & /*recv_data*/) -{ - for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) - SetTutorialInt(i, 0xFFFFFFFF); -} - -void WorldSession::HandleTutorialReset(WorldPacket & /*recv_data*/) -{ - for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) - SetTutorialInt(i, 0x00000000); -} - -void WorldSession::HandleSetWatchedFactionOpcode(WorldPacket & recv_data) -{ - sLog->outStaticDebug("WORLD: Received CMSG_SET_WATCHED_FACTION"); - uint32 fact; - recv_data >> fact; - GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fact); -} - -void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket & recv_data) -{ - sLog->outStaticDebug("WORLD: Received CMSG_SET_FACTION_INACTIVE"); - uint32 replistid; - uint8 inactive; - recv_data >> replistid >> inactive; - - _player->GetReputationMgr().SetInactive(replistid, inactive); -} - -void WorldSession::HandleShowingHelmOpcode(WorldPacket& recv_data) -{ - sLog->outStaticDebug("CMSG_SHOWING_HELM for %s", _player->GetName()); - recv_data.read_skip<uint8>(); // unknown, bool? - _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM); -} - -void WorldSession::HandleShowingCloakOpcode(WorldPacket& recv_data) -{ - sLog->outStaticDebug("CMSG_SHOWING_CLOAK for %s", _player->GetName()); - recv_data.read_skip<uint8>(); // unknown, bool? - _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK); -} - -void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) -{ - uint64 guid; - std::string newName; - - recv_data >> guid; - recv_data >> newName; - - // prevent character rename to invalid name - if (!normalizePlayerName(newName)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_NAME_NO_NAME); - SendPacket(&data); - return; - } - - uint8 res = ObjectMgr::CheckPlayerName(newName, true); - if (res != CHAR_NAME_SUCCESS) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(res); - SendPacket(&data); - return; - } - - // check name limitations - if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_NAME_RESERVED); - SendPacket(&data); - return; - } - - // Ensure that the character belongs to the current account, that rename at login is enabled - // and that there is no character with the desired new name - _charRenameCallback.SetParam(newName); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_FREE_NAME); - - stmt->setUInt32(0, GUID_LOPART(guid)); - stmt->setUInt32(1, GetAccountId()); - stmt->setUInt16(2, AT_LOGIN_RENAME); - stmt->setUInt16(3, AT_LOGIN_RENAME); - stmt->setString(4, newName); - - _charRenameCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); -} - -void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string newName) -{ - if (!result) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - Field* fields = result->Fetch(); - - uint32 guidLow = fields[0].GetUInt32(); - std::string oldName = fields[1].GetString(); - - uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); - - // Update name and at_login flag in the db - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME); - - stmt->setString(0, newName); - stmt->setUInt16(1, AT_LOGIN_RENAME); - stmt->setUInt32(2, guidLow); - - CharacterDatabase.Execute(stmt); - - // Removed declined name from db - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME); - - stmt->setUInt32(0, guidLow); - - CharacterDatabase.Execute(stmt); - - sLog->outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), guidLow, newName.c_str()); - - WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newName.size()+1)); - data << uint8(RESPONSE_SUCCESS); - data << uint64(guid); - data << newName; - SendPacket(&data); - - sWorld->UpdateCharacterNameData(guidLow, newName); -} - -void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) -{ - uint64 guid; - - recv_data >> guid; - - // not accept declined names for unsupported languages - std::string name; - if (!sObjectMgr->GetPlayerNameByGUID(guid, name)) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - std::wstring wname; - if (!Utf8toWStr(name, wname)) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - if (!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - std::string name2; - DeclinedName declinedname; - - recv_data >> name2; - - if (name2 != name) // character have different name - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - { - recv_data >> declinedname.name[i]; - if (!normalizePlayerName(declinedname.name[i])) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - } - - if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - CharacterDatabase.EscapeString(declinedname.name[i]); - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); - trans->PAppend("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u', '%s', '%s', '%s', '%s', '%s')", - GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); - CharacterDatabase.CommitTransaction(trans); - - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(0); // OK - data << uint64(guid); - SendPacket(&data); -} - -void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ALTER_APPEARANCE"); - - uint32 Hair, Color, FacialHair, SkinColor; - recv_data >> Hair >> Color >> FacialHair >> SkinColor; - - BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); - - if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender()) - return; - - BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair); - - if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender()) - return; - - BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor); - - if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender())) - return; - - uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id, bs_skinColor); - - // 0 - ok - // 1, 3 - not enough money - // 2 - you have to seat on barber chair - if (!_player->HasEnoughMoney(Cost)) - { - WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); - data << uint32(1); // no money - SendPacket(&data); - return; - } - else - { - WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); - data << uint32(0); // ok - SendPacket(&data); - } - - _player->ModifyMoney(-int32(Cost)); // it isn't free - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, Cost); - - _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); - _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); - _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id)); - if (bs_skinColor) - _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id)); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); - - _player->SetStandState(0); // stand up -} - -void WorldSession::HandleRemoveGlyph(WorldPacket & recv_data) -{ - uint32 slot; - recv_data >> slot; - - if (slot >= MAX_GLYPH_SLOT_INDEX) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); - return; - } - - if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot)) - { - if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph)) - { - _player->RemoveAurasDueToSpell(gp->SpellId); - _player->SetGlyph(slot, 0); - _player->SendTalentsInfoData(false); - } - } -} - -void WorldSession::HandleCharCustomize(WorldPacket& recv_data) -{ - uint64 guid; - std::string newName; - - recv_data >> guid; - recv_data >> newName; - - uint8 gender, skin, face, hairStyle, hairColor, facialHair; - recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; - - QueryResult result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); - if (!result) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - Field* fields = result->Fetch(); - uint32 at_loginFlags = fields[0].GetUInt16(); - - if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - // prevent character rename to invalid name - if (!normalizePlayerName(newName)) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_NAME_NO_NAME); - SendPacket(&data); - return; - } - - uint8 res = ObjectMgr::CheckPlayerName(newName, true); - if (res != CHAR_NAME_SUCCESS) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(res); - SendPacket(&data); - return; - } - - // check name limitations - if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newName)) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_NAME_RESERVED); - SendPacket(&data); - return; - } - - // character with this name already exist - if (uint64 newguid = sObjectMgr->GetPlayerGUIDByName(newName)) - { - if (newguid != guid) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_CREATE_NAME_IN_USE); - SendPacket(&data); - return; - } - } - - if (QueryResult oldNameResult = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid ='%u'", GUID_LOPART(guid))) - { - std::string oldname = oldNameResult->Fetch()[0].GetString(); - std::string IP_str = GetRemoteAddress(); - sLog->outChar("Account: %d (IP: %s), Character[%s] (guid:%u) Customized to: %s", GetAccountId(), IP_str.c_str(), oldname.c_str(), GUID_LOPART(guid), newName.c_str()); - } - Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN); - - stmt->setString(0, newName); - stmt->setUInt16(1, uint16(AT_LOGIN_CUSTOMIZE)); - stmt->setUInt32(2, GUID_LOPART(guid)); - - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME); - - stmt->setUInt32(0, GUID_LOPART(guid)); - - CharacterDatabase.Execute(stmt); - - sWorld->UpdateCharacterNameData(GUID_LOPART(guid), newName, gender); - - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newName.size()+1)+6); - data << uint8(RESPONSE_SUCCESS); - data << uint64(guid); - data << newName; - data << uint8(gender); - data << uint8(skin); - data << uint8(face); - data << uint8(hairStyle); - data << uint8(hairColor); - data << uint8(facialHair); - SendPacket(&data); -} - -void WorldSession::HandleEquipmentSetSave(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_SAVE"); - - uint64 setGuid; - recv_data.readPackGUID(setGuid); - - uint32 index; - recv_data >> index; - if (index >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount - return; - - std::string name; - recv_data >> name; - - std::string iconName; - recv_data >> iconName; - - EquipmentSet eqSet; - - eqSet.Guid = setGuid; - eqSet.Name = name; - eqSet.IconName = iconName; - eqSet.state = EQUIPMENT_SET_NEW; - - for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) - { - uint64 itemGuid; - recv_data.readPackGUID(itemGuid); - - Item* item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - - if (!item && itemGuid) // cheating check 1 - return; - - if (item && item->GetGUID() != itemGuid) // cheating check 2 - return; - - eqSet.Items[i] = GUID_LOPART(itemGuid); - } - - _player->SetEquipmentSet(index, eqSet); -} - -void WorldSession::HandleEquipmentSetDelete(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_DELETE"); - - uint64 setGuid; - recv_data.readPackGUID(setGuid); - - _player->DeleteEquipmentSet(setGuid); -} - -void WorldSession::HandleEquipmentSetUse(WorldPacket &recv_data) -{ - if (_player->isInCombat()) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_EQUIPMENT_SET_USE"); - - for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) - { - uint64 itemGuid; - recv_data.readPackGUID(itemGuid); - - uint8 srcbag, srcslot; - recv_data >> srcbag >> srcslot; - - sLog->outDebug(LOG_FILTER_PLAYER_ITEMS, "Item " UI64FMTD ": srcbag %u, srcslot %u", itemGuid, srcbag, srcslot); - - Item* item = _player->GetItemByGuid(itemGuid); - - uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8); - - if (!item) - { - Item* uItem = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (!uItem) - continue; - - ItemPosCountVec sDest; - InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false); - if (msg == EQUIP_ERR_OK) - { - _player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true); - _player->StoreItem(sDest, uItem, true); - } - else - _player->SendEquipError(msg, uItem, NULL); - - continue; - } - - if (item->GetPos() == dstpos) - continue; - - _player->SwapItem(item->GetPos(), dstpos); - } - - WorldPacket data(SMSG_EQUIPMENT_SET_USE_RESULT, 1); - data << uint8(0); // 4 - equipment swap failed - inventory is full - SendPacket(&data); -} - -void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) -{ - // TODO: Move queries to prepared statements - uint64 guid; - std::string newname; - uint8 gender, skin, face, hairStyle, hairColor, facialHair, race; - recv_data >> guid; - recv_data >> newname; - recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face >> race; - - uint32 lowGuid = GUID_LOPART(guid); - QueryResult result = CharacterDatabase.PQuery("SELECT class, level, at_login FROM characters WHERE guid ='%u'", lowGuid); - if (!result) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - Field* fields = result->Fetch(); - uint32 playerClass = fields[0].GetUInt32(); - uint32 level = fields[1].GetUInt32(); - uint32 at_loginFlags = fields[2].GetUInt16(); - uint32 used_loginFlag = ((recv_data.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION); - - if (!sObjectMgr->GetPlayerInfo(race, playerClass)) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - if (!(at_loginFlags & used_loginFlag)) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - if (AccountMgr::IsPlayerAccount(GetSecurity())) - { - uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK); - if ((1 << (race - 1)) & raceMaskDisabled) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - } - - // prevent character rename to invalid name - if (!normalizePlayerName(newname)) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_NAME_NO_NAME); - SendPacket(&data); - return; - } - - uint8 res = ObjectMgr::CheckPlayerName(newname, true); - if (res != CHAR_NAME_SUCCESS) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(res); - SendPacket(&data); - return; - } - - // check name limitations - if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(newname)) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_NAME_RESERVED); - SendPacket (&data); - return; - } - - // character with this name already exist - if (uint64 newguid = sObjectMgr->GetPlayerGUIDByName(newname)) - { - if (newguid != guid) - { - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); - data << uint8(CHAR_CREATE_NAME_IN_USE); - SendPacket(&data); - return; - } - } - - CharacterDatabase.EscapeString(newname); - Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("UPDATE `characters` SET name='%s', race='%u', at_login=at_login & ~ %u WHERE guid='%u'", newname.c_str(), race, used_loginFlag, lowGuid); - trans->PAppend("DELETE FROM character_declinedname WHERE guid ='%u'", lowGuid); - sWorld->UpdateCharacterNameData(GUID_LOPART(guid), newname, gender, race); - - BattlegroundTeamId team = BG_TEAM_ALLIANCE; - - // Search each faction is targeted - switch (race) - { - case RACE_ORC: - case RACE_GOBLIN: - case RACE_TAUREN: - case RACE_UNDEAD_PLAYER: - case RACE_TROLL: - case RACE_BLOODELF: - team = BG_TEAM_HORDE; - break; - default: - break; - } - - // Switch Languages - // delete all languages first - trans->PAppend("DELETE FROM `character_skills` WHERE `skill` IN (98, 113, 759, 111, 313, 109, 115, 315, 673, 137, 791, 792) AND `guid`='%u'", lowGuid); - - // now add them back - if (team == BG_TEAM_ALLIANCE) - { - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 98, 300, 300)", lowGuid); - switch (race) - { - case RACE_DWARF: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 111, 300, 300)", lowGuid); - break; - case RACE_DRAENEI: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 759, 300, 300)", lowGuid); - break; - case RACE_GNOME: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 313, 300, 300)", lowGuid); - break; - case RACE_NIGHTELF: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 113, 300, 300)", lowGuid); - break; - case RACE_WORGEN: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 791, 300, 300)", lowGuid); - break; - } - } - else if (team == BG_TEAM_HORDE) - { - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 109, 300, 300)", lowGuid); - switch (race) - { - case RACE_UNDEAD_PLAYER: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 673, 300, 300)", lowGuid); - break; - case RACE_TAUREN: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 115, 300, 300)", lowGuid); - break; - case RACE_TROLL: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 315, 300, 300)", lowGuid); - break; - case RACE_BLOODELF: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 137, 300, 300)", lowGuid); - break; - case RACE_GOBLIN: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 792, 300, 300)", lowGuid); - break; - } - } - - if (recv_data.GetOpcode() == CMSG_CHAR_FACTION_CHANGE) - { - // Delete all Flypaths - trans->PAppend("UPDATE `characters` SET taxi_path = '' WHERE guid ='%u'", lowGuid); - - if (level > 7) - { - // Update Taxi path - // this doesn't seem to be 100% blizzlike... but it can't really be helped. - std::ostringstream taximaskstream; - uint32 numFullTaximasks = level / 7; - if (numFullTaximasks > 11) - numFullTaximasks = 11; - if (team == BG_TEAM_ALLIANCE) - { - if (playerClass != CLASS_DEATH_KNIGHT) - { - for (uint8 i = 0; i < numFullTaximasks; ++i) - taximaskstream << uint32(sAllianceTaxiNodesMask[i]) << ' '; - } - else - { - for (uint8 i = 0; i < numFullTaximasks; ++i) - taximaskstream << uint32(sAllianceTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' '; - } - } - else - { - if (playerClass != CLASS_DEATH_KNIGHT) - { - for (uint8 i = 0; i < numFullTaximasks; ++i) - taximaskstream << uint32(sHordeTaxiNodesMask[i]) << ' '; - } - else - { - for (uint8 i = 0; i < numFullTaximasks; ++i) - taximaskstream << uint32(sHordeTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' '; - } - } - - uint32 numEmptyTaximasks = 11 - numFullTaximasks; - for (uint8 i = 0; i < numEmptyTaximasks; ++i) - taximaskstream << "0 "; - taximaskstream << '0'; - std::string taximask = taximaskstream.str(); - trans->PAppend("UPDATE `characters` SET `taximask`= '%s' WHERE `guid` = '%u'", taximask.c_str(), lowGuid); - } - - // Delete all current quests - trans->PAppend("DELETE FROM `character_queststatus` WHERE guid ='%u'", GUID_LOPART(guid)); - - // Delete record of the faction old completed quests - { - std::ostringstream quests; - ObjectMgr::QuestMap const& qTemplates = sObjectMgr->GetQuestTemplates(); - for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) - { - Quest *qinfo = iter->second; - uint32 requiredRaces = qinfo->GetRequiredRaces(); - if (team == BG_TEAM_ALLIANCE) - { - if (requiredRaces & RACEMASK_ALLIANCE) - { - quests << uint32(qinfo->GetQuestId()); - quests << ','; - } - } - else // if (team == BG_TEAM_HORDE) - { - if (requiredRaces & RACEMASK_HORDE) - { - quests << uint32(qinfo->GetQuestId()); - quests << ','; - } - } - } - - std::string questsStr = quests.str(); - questsStr = questsStr.substr(0, questsStr.length() - 1); - - if (!questsStr.empty()) - trans->PAppend("DELETE FROM `character_queststatus_rewarded` WHERE guid='%u' AND quest IN (%s)", lowGuid, questsStr.c_str()); - } - - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) - { - // Reset guild - if (QueryResult result = CharacterDatabase.PQuery("SELECT guildid FROM `guild_member` WHERE guid ='%u'", lowGuid)) - if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32())) - guild->DeleteMember(MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER)); - } - - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND)) - { - // Delete Friend List - trans->PAppend("DELETE FROM `character_social` WHERE `guid`= '%u'", lowGuid); - trans->PAppend("DELETE FROM `character_social` WHERE `friend`= '%u'", lowGuid); - } - - // Leave Arena Teams - Player::LeaveAllArenaTeams(guid); - - // Reset homebind and position - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_HOMEBIND); - stmt->setUInt32(0, lowGuid); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_HOMEBIND); - stmt->setUInt32(0, lowGuid); - if (team == BG_TEAM_ALLIANCE) - { - stmt->setUInt16(1, 0); - stmt->setUInt16(2, 1519); - stmt->setFloat (3, -8867.68f); - stmt->setFloat (4, 673.373f); - stmt->setFloat (5, 97.9034f); - Player::SavePositionInDB(0, -8867.68f, 673.373f, 97.9034f, 0.0f, 1519, lowGuid); - } - else - { - stmt->setUInt16(1, 1); - stmt->setUInt16(2, 1637); - stmt->setFloat (3, 1633.33f); - stmt->setFloat (4, -4439.11f); - stmt->setFloat (5, 15.7588f); - Player::SavePositionInDB(1, 1633.33f, -4439.11f, 15.7588f, 0.0f, 1637, lowGuid); - } - trans->Append(stmt); - - // Achievement conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_achievements.begin(); it != sObjectMgr->factionchange_achievements.end(); ++it) - { - uint32 achiev_alliance = it->first; - uint32 achiev_horde = it->second; - trans->PAppend("DELETE FROM `character_achievement` WHERE `achievement`=%u AND `guid`=%u", - team == BG_TEAM_ALLIANCE ? achiev_alliance : achiev_horde, lowGuid); - trans->PAppend("UPDATE `character_achievement` SET achievement = '%u' where achievement = '%u' AND guid = '%u'", - team == BG_TEAM_ALLIANCE ? achiev_alliance : achiev_horde, team == BG_TEAM_ALLIANCE ? achiev_horde : achiev_alliance, lowGuid); - } - - // Item conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_items.begin(); it != sObjectMgr->factionchange_items.end(); ++it) - { - uint32 item_alliance = it->first; - uint32 item_horde = it->second; - trans->PAppend("UPDATE `item_instance` ii, `character_inventory` ci SET ii.itemEntry = '%u' WHERE ii.itemEntry = '%u' AND ci.guid = '%u' AND ci.item = ii.guid", - team == BG_TEAM_ALLIANCE ? item_alliance : item_horde, team == BG_TEAM_ALLIANCE ? item_horde : item_alliance, guid); - } - - // Spell conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_spells.begin(); it != sObjectMgr->factionchange_spells.end(); ++it) - { - uint32 spell_alliance = it->first; - uint32 spell_horde = it->second; - trans->PAppend("DELETE FROM `character_spell` WHERE `spell`=%u AND `guid`=%u", - team == BG_TEAM_ALLIANCE ? spell_alliance : spell_horde, lowGuid); - trans->PAppend("UPDATE `character_spell` SET spell = '%u' where spell = '%u' AND guid = '%u'", - team == BG_TEAM_ALLIANCE ? spell_alliance : spell_horde, team == BG_TEAM_ALLIANCE ? spell_horde : spell_alliance, lowGuid); - } - - // Reputation conversion - for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->factionchange_reputations.begin(); it != sObjectMgr->factionchange_reputations.end(); ++it) - { - uint32 reputation_alliance = it->first; - uint32 reputation_horde = it->second; - trans->PAppend("DELETE FROM character_reputation WHERE faction = '%u' AND guid = '%u'", - team == BG_TEAM_ALLIANCE ? reputation_alliance : reputation_horde, lowGuid); - trans->PAppend("UPDATE `character_reputation` SET faction = '%u' where faction = '%u' AND guid = '%u'", - team == BG_TEAM_ALLIANCE ? reputation_alliance : reputation_horde, team == BG_TEAM_ALLIANCE ? reputation_horde : reputation_alliance, lowGuid); - } - } - - CharacterDatabase.CommitTransaction(trans); - - std::string IP_str = GetRemoteAddress(); - sLog->outDebug(LOG_FILTER_UNITS, "Account: %d (IP: %s), Character guid: %u Change Race/Faction to: %s", GetAccountId(), IP_str.c_str(), lowGuid, newname.c_str()); - - WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1 + 8 + (newname.size() + 1) + 1 + 1 + 1 + 1 + 1 + 1 + 1); - data << uint8(RESPONSE_SUCCESS); - data << uint64(guid); - data << newname; - data << uint8(gender); - data << uint8(skin); - data << uint8(face); - data << uint8(hairStyle); - data << uint8(hairColor); - data << uint8(facialHair); - data << uint8(race); - SendPacket(&data); -} - -void WorldSession::HandleRandomizeCharNameOpcode(WorldPacket& recv_data) -{ - uint8 gender, race; - - recv_data >> gender; - recv_data >> race; - - if (!Player::IsValidRace(race)) - { - sLog->outError("Invalid race (%u) sent by accountId: %u", race, GetAccountId()); - return; - } - - if (!Player::IsValidGender(gender)) - { - sLog->outError("Invalid gender (%u) sent by accountId: %u", gender, GetAccountId()); - return; - } - - WorldPacket data(SMSG_RANDOMIZE_CHAR_NAME, 10); - data << uint8(128); // unk1 - data << *GetRandomCharacterName(race, gender); - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp deleted file mode 100755 index 3a47f214099..00000000000 --- a/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp +++ /dev/null @@ -1,798 +0,0 @@ -/* - * 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 "GuildMgr.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "DatabaseEnv.h" - -#include "CellImpl.h" -#include "Chat.h" -#include "ChannelMgr.h" -#include "GridNotifiersImpl.h" -#include "Group.h" -#include "Guild.h" -#include "Language.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" -#include "SpellAuras.h" -#include "SpellAuraEffects.h" -#include "Util.h" -#include "ScriptMgr.h" -#include "AccountMgr.h" - -bool WorldSession::processChatmessageFurtherAfterSecurityChecks(std::string& msg, uint32 lang) -{ - if (lang != LANG_ADDON) - { - // strip invisible characters for non-addon messages - if (sWorld->getBoolConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) - stripLineInvisibleChars(msg); - - if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) && AccountMgr::IsPlayerAccount(GetSecurity()) - && !ChatHandler(this).isValidChatMessage(msg.c_str())) - { - sLog->outError("Player %s (GUID: %u) sent a chatmessage with an invalid link: %s", GetPlayer()->GetName(), - GetPlayer()->GetGUIDLow(), msg.c_str()); - if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) - KickPlayer(); - return false; - } - } - - return true; -} - -void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) -{ - uint32 type = 0; - uint32 lang; - - switch(recvData.GetOpcode()) - { - case CMSG_MESSAGECHAT_SAY: - type = CHAT_MSG_SAY; - break; - case CMSG_MESSAGECHAT_YELL: - type = CHAT_MSG_YELL; - break; - case CMSG_MESSAGECHAT_CHANNEL: - type = CHAT_MSG_CHANNEL; - break; - case CMSG_MESSAGECHAT_WHISPER: - type = CHAT_MSG_WHISPER; - break; - case CMSG_MESSAGECHAT_GUILD: - type = CHAT_MSG_GUILD; - break; - //case CMSG_MESSAGECHAT_OFFICER: - // type = CHAT_MSG_OFFICER; - // break; - case CMSG_MESSAGECHAT_AFK: - type = CHAT_MSG_AFK; - break; - case CMSG_MESSAGECHAT_DND: - type = CHAT_MSG_DND; - break; - case CMSG_MESSAGECHAT_EMOTE: - type = CHAT_MSG_EMOTE; - break; - case CMSG_MESSAGECHAT_PARTY: - type = CHAT_MSG_PARTY; - break; - //case CMSG_MESSAGECHAT_PARTY_LEADER: - // type = CHAT_MSG_PARTY_LEADER; - // break; - //case CMSG_MESSAGECHAT_RAID: - // type = CHAT_MSG_RAID; - // break; - //case CMSG_MESSAGECHAT_RAID_LEADER: - // type = CHAT_MSG_RAID_LEADER; - // break; - //case CMSG_MESSAGECHAT_BATTLEGROUND: - // type = CHAT_MSG_BATTLEGROUND; - // break; - //case CMSG_MESSAGECHAT_BATTLEGROUND_LEADER: - // type = CHAT_MSG_BATTLEGROUND_LEADER; - // break; - //case CMSG_MESSAGECHAT_RAID_WARNING: - // type = CHAT_MSG_RAID_WARNING; - // break; - default: - sLog->outDetail("HandleMessagechatOpcode : Unknown chat opcode (%u)", recvData.GetOpcode()); - recvData.hexlike(); - return; - } - - if (type >= MAX_CHAT_MSG_TYPE) - { - sLog->outError("CHAT: Wrong message type received: %u", type); - recvData.rfinish(); - return; - } - - Player* sender = GetPlayer(); - - //sLog->outDebug("CHAT: packet received. type %u, lang %u", type, lang); - - // no language sent with emote packet. - if (type != CHAT_MSG_EMOTE) - { - recvData >> lang; - - // prevent talking at unknown language (cheating) - LanguageDesc const* langDesc = GetLanguageDescByID(lang); - if (!langDesc) - { - SendNotification(LANG_UNKNOWN_LANGUAGE); - recvData.rfinish(); - return; - } - if (langDesc->skill_id != 0 && !sender->HasSkill(langDesc->skill_id)) - { - // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) - Unit::AuraEffectList const& langAuras = sender->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE); - bool foundAura = false; - for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) - { - if ((*i)->GetMiscValue() == int32(lang)) - { - foundAura = true; - break; - } - } - if (!foundAura) - { - SendNotification(LANG_NOT_LEARNED_LANGUAGE); - recvData.rfinish(); - return; - } - } - - if (lang == LANG_ADDON) - { - if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON)) - { - std::string msg = ""; - recvData >> msg; - - if (msg.empty()) - return; - - sScriptMgr->OnPlayerChat(sender, uint32(CHAT_MSG_ADDON), lang, msg); - } - - // Disabled addon channel? - if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL)) - return; - } - // LANG_ADDON should not be changed nor be affected by flood control - else - { - // send in universal language if player in .gmon mode (ignore spell effects) - if (sender->isGameMaster()) - lang = LANG_UNIVERSAL; - else - { - // send in universal language in two side iteration allowed mode - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)) - lang = LANG_UNIVERSAL; - else - { - switch (type) - { - case CHAT_MSG_PARTY: - case CHAT_MSG_PARTY_LEADER: - case CHAT_MSG_RAID: - case CHAT_MSG_RAID_LEADER: - case CHAT_MSG_RAID_WARNING: - // allow two side chat at group channel if two side group allowed - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) - lang = LANG_UNIVERSAL; - break; - case CHAT_MSG_GUILD: - case CHAT_MSG_OFFICER: - // allow two side chat at guild channel if two side guild allowed - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) - lang = LANG_UNIVERSAL; - break; - } - } - - // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) - Unit::AuraEffectList const& ModLangAuras = sender->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE); - if (!ModLangAuras.empty()) - lang = ModLangAuras.front()->GetMiscValue(); - } - - if (!sender->CanSpeak()) - { - std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); - SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); - recvData.rfinish(); // Prevent warnings - return; - } - - if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) - sender->UpdateSpeakTime(); - } - } - - if (sender->HasAura(1852) && type != CHAT_MSG_WHISPER) - { - std::string msg=""; - recvData >> msg; - - SendNotification(GetTrinityString(LANG_GM_SILENCE), sender->GetName()); - return; - } - - std::string to, channel, msg; - bool ignoreChecks = false; - switch (type) - { - case CHAT_MSG_SAY: - case CHAT_MSG_EMOTE: - case CHAT_MSG_YELL: - case CHAT_MSG_PARTY: - case CHAT_MSG_PARTY_LEADER: - case CHAT_MSG_GUILD: - case CHAT_MSG_OFFICER: - case CHAT_MSG_RAID: - case CHAT_MSG_RAID_LEADER: - case CHAT_MSG_RAID_WARNING: - case CHAT_MSG_BATTLEGROUND: - case CHAT_MSG_BATTLEGROUND_LEADER: - recvData >> msg; - break; - case CHAT_MSG_WHISPER: - recvData >> msg; - recvData >> to; - break; - case CHAT_MSG_CHANNEL: - recvData >> msg; - recvData >> channel; - break; - case CHAT_MSG_AFK: - case CHAT_MSG_DND: - recvData >> msg; - ignoreChecks = true; - break; - } - - if (!ignoreChecks) - { - if (msg.empty()) - return; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - return; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - return; - } - - switch (type) - { - case CHAT_MSG_SAY: - case CHAT_MSG_EMOTE: - case CHAT_MSG_YELL: - { - if (sender->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_SAY_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_SAY_REQ), sWorld->getIntConfig(CONFIG_CHAT_SAY_LEVEL_REQ)); - return; - } - - if (type == CHAT_MSG_SAY) - sender->Say(msg, lang); - else if (type == CHAT_MSG_EMOTE) - sender->TextEmote(msg); - else if (type == CHAT_MSG_YELL) - sender->Yell(msg, lang); - } break; - case CHAT_MSG_WHISPER: - { - if (sender->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_WHISPER_REQ), sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)); - return; - } - - if (!normalizePlayerName(to)) - { - SendPlayerNotFoundNotice(to); - break; - } - - Player* receiver = sObjectAccessor->FindPlayerByName(to.c_str()); - bool senderIsPlayer = AccountMgr::IsPlayerAccount(GetSecurity()); - bool receiverIsPlayer = AccountMgr::IsPlayerAccount(receiver ? receiver->GetSession()->GetSecurity() : SEC_PLAYER); - if (!receiver || (senderIsPlayer && !receiverIsPlayer && !receiver->isAcceptWhispers() && !receiver->IsInWhisperWhiteList(sender->GetGUID()))) - { - SendPlayerNotFoundNotice(to); - return; - } - - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && senderIsPlayer && receiverIsPlayer) - if (GetPlayer()->GetTeam() != receiver->GetTeam()) - { - SendWrongFactionNotice(); - return; - } - - if (GetPlayer()->HasAura(1852) && !receiver->isGameMaster()) - { - SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); - return; - } - - // If player is a Gamemaster and doesn't accept whisper, we auto-whitelist every player that the Gamemaster is talking to - if (!senderIsPlayer && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID())) - sender->AddWhisperWhiteList(receiver->GetGUID()); - - GetPlayer()->Whisper(msg, lang, receiver->GetGUID()); - } break; - case CHAT_MSG_PARTY: - case CHAT_MSG_PARTY_LEADER: - { - // if player is in battleground, he cannot say to battleground members by /p - Group* group = GetPlayer()->GetOriginalGroup(); - if (!group) - { - group = _player->GetGroup(); - if (!group || group->isBGGroup()) - return; - } - - if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(_player->GetGUID())) - return; - - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, uint8(type), lang, NULL, 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); - } break; - case CHAT_MSG_GUILD: - { - if (GetPlayer()->GetGuildId()) - { - if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) - { - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, guild); - - guild->BroadcastToGuild(this, false, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); - } - } - } break; - case CHAT_MSG_OFFICER: - { - if (GetPlayer()->GetGuildId()) - { - if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) - { - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, guild); - - guild->BroadcastToGuild(this, true, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); - } - } - } break; - case CHAT_MSG_RAID: - { - // if player is in battleground, he cannot say to battleground members by /ra - Group* group = GetPlayer()->GetOriginalGroup(); - if (!group) - { - group = GetPlayer()->GetGroup(); - if (!group || group->isBGGroup() || !group->isRaidGroup()) - return; - } - - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - } break; - case CHAT_MSG_RAID_LEADER: - { - // if player is in battleground, he cannot say to battleground members by /ra - Group* group = GetPlayer()->GetOriginalGroup(); - if (!group) - { - group = GetPlayer()->GetGroup(); - if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) - return; - } - - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - } break; - case CHAT_MSG_RAID_WARNING: - { - Group* group = GetPlayer()->GetGroup(); - if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())) || group->isBGGroup()) - return; - - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - //in battleground, raid warning is sent only to players in battleground - code is ok - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - } break; - case CHAT_MSG_BATTLEGROUND: - { - //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() - Group* group = GetPlayer()->GetGroup(); - if (!group || !group->isBGGroup()) - return; - - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - } break; - case CHAT_MSG_BATTLEGROUND_LEADER: - { - // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() - Group* group = GetPlayer()->GetGroup(); - if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) - return; - - sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - } break; - case CHAT_MSG_CHANNEL: - { - if (AccountMgr::IsPlayerAccount(GetSecurity())) - { - if (_player->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_CHANNEL_REQ), sWorld->getIntConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)); - return; - } - } - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - - if (Channel* chn = cMgr->GetChannel(channel, _player)) - { - sScriptMgr->OnPlayerChat(_player, type, lang, msg, chn); - - chn->Say(_player->GetGUID(), msg.c_str(), lang); - } - } - } break; - case CHAT_MSG_AFK: - { - if ((msg.empty() || !_player->isAFK()) && !_player->isInCombat()) - { - if (!_player->isAFK()) - { - if (msg.empty()) - msg = GetTrinityString(LANG_PLAYER_AFK_DEFAULT); - _player->afkMsg = msg; - } - - sScriptMgr->OnPlayerChat(_player, type, lang, msg); - - _player->ToggleAFK(); - if (_player->isAFK() && _player->isDND()) - _player->ToggleDND(); - } - } break; - case CHAT_MSG_DND: - { - if (msg.empty() || !_player->isDND()) - { - if (!_player->isDND()) - { - if (msg.empty()) - msg = GetTrinityString(LANG_PLAYER_DND_DEFAULT); - _player->dndMsg = msg; - } - - sScriptMgr->OnPlayerChat(_player, type, lang, msg); - - _player->ToggleDND(); - if (_player->isDND() && _player->isAFK()) - _player->ToggleAFK(); - } - } break; - default: - sLog->outError("CHAT: unknown message type %u, lang: %u", type, lang); - break; - } -} - -void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recvData) -{ - Player* sender = GetPlayer(); - ChatMsg type; - - switch (recvData.GetOpcode()) - { - case CMSG_MESSAGECHAT_ADDON_BATTLEGROUND: - type = CHAT_MSG_BATTLEGROUND; - break; - case CMSG_MESSAGECHAT_ADDON_GUILD: - type = CHAT_MSG_GUILD; - break; - case CMSG_MESSAGECHAT_ADDON_PARTY: - type = CHAT_MSG_PARTY; - break; - case CMSG_MESSAGECHAT_ADDON_RAID: - type = CHAT_MSG_RAID; - break; - case CMSG_MESSAGECHAT_ADDON_WHISPER: - type = CHAT_MSG_WHISPER; - break; - default: - sLog->outDetail("HandleAddonMessagechatOpcode: Unknown addon chat opcode (%u)", recvData.GetOpcode()); - recvData.hexlike(); - return; - } - - std::string message = ""; - std::string prefix = ""; - std::string targetName = ""; - - if (type == CHAT_MSG_WHISPER) - recvData >> prefix >> targetName >> message; - else - recvData >> message >> prefix; - - // Logging enabled? - if (sWorld->getBoolConfig(CONFIG_CHATLOG_ADDON)) - { - if (message.empty()) - return; - - // Weird way to log stuff... - sScriptMgr->OnPlayerChat(sender, CHAT_MSG_ADDON, LANG_ADDON, message); - } - - // Disabled addon channel? - if (!sWorld->getBoolConfig(CONFIG_ADDON_CHANNEL)) - return; - - switch (type) - { - case CHAT_MSG_BATTLEGROUND: - { - Group* group = sender->GetGroup(); - if (!group || !group->isBGGroup()) - return; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", 0, message.c_str(), NULL); - group->BroadcastPacket(&data, false); - break; - } - case CHAT_MSG_GUILD: - { - if (sender->GetGuildId()) - if (Guild* guild = sGuildMgr->GetGuildById(sender->GetGuildId())) - guild->BroadcastToGuild(this, false, message, LANG_ADDON); - break; - } - case CHAT_MSG_WHISPER: - { - if (!normalizePlayerName(targetName)) - break; - Player* receiver = sObjectAccessor->FindPlayerByName(targetName.c_str()); - if (!receiver) - break; - - sender->Whisper(message, LANG_ADDON, receiver->GetGUID()); - break; - } - // Messages sent to "RAID" while in a party will get delivered to "PARTY" - case CHAT_MSG_PARTY: - case CHAT_MSG_RAID: - { - - Group* group = sender->GetGroup(); - if (!group || group->isBGGroup()) - break; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", 0, message.c_str(), NULL); - group->BroadcastPacket(&data, true, -1, group->GetMemberGroup(sender->GetGUID())); - break; - } - default: - { - sLog->outError("HandleAddonMessagechatOpcode: unknown addon message type %u", type); - break; - } - } -} - -void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) -{ - if (!GetPlayer()->isAlive() || GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - return; - - uint32 emote; - recv_data >> emote; - sScriptMgr->OnPlayerEmote(GetPlayer(), emote); - GetPlayer()->HandleEmoteCommand(emote); -} - -namespace Trinity -{ - class EmoteChatBuilder - { - public: - EmoteChatBuilder(Player const& player, uint32 text_emote, uint32 emote_num, Unit const* target) - : i_player(player), i_text_emote(text_emote), i_emote_num(emote_num), i_target(target) {} - - void operator()(WorldPacket& data, LocaleConstant loc_idx) - { - char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL; - uint32 namlen = (nam ? strlen(nam) : 0) + 1; - - data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); - data << i_player.GetGUID(); - data << (uint32)i_text_emote; - data << i_emote_num; - data << (uint32)namlen; - if (namlen > 1) - data.append(nam, namlen); - else - data << (uint8)0x00; - } - - private: - Player const& i_player; - uint32 i_text_emote; - uint32 i_emote_num; - Unit const* i_target; - }; -} // namespace Trinity - -void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) -{ - if (!GetPlayer()->isAlive()) - return; - - if (!GetPlayer()->CanSpeak()) - { - std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); - SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); - return; - } - - uint32 text_emote, emoteNum; - uint64 guid; - - recv_data >> text_emote; - recv_data >> emoteNum; - recv_data >> guid; - - sScriptMgr->OnPlayerTextEmote(GetPlayer(), text_emote, emoteNum, guid); - - EmotesTextEntry const* em = sEmotesTextStore.LookupEntry(text_emote); - if (!em) - return; - - uint32 emote_anim = em->textid; - - switch (emote_anim) - { - case EMOTE_STATE_SLEEP: - case EMOTE_STATE_SIT: - case EMOTE_STATE_KNEEL: - case EMOTE_ONESHOT_NONE: - break; - default: - // Only allow text-emotes for "dead" entities (feign death included) - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - break; - GetPlayer()->HandleEmoteCommand(emote_anim); - break; - } - - Unit* unit = ObjectAccessor::GetUnit(*_player, guid); - - CellCoord p = Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); - - Cell cell(p); - cell.SetNoCreate(); - - Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); - Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > emote_do(emote_builder); - Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); - TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::EmoteChatBuilder> >, WorldTypeMapContainer> message(emote_worker); - cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); - - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); - - //Send scripted event call - if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); -} - -void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data) -{ - uint64 iguid; - uint8 unk; - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_CHAT_IGNORED"); - - recv_data >> iguid; - recv_data >> unk; // probably related to spam reporting - - Player* player = ObjectAccessor::FindPlayer(iguid); - if (!player || !player->GetSession()) - return; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(), NULL); - player->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleChannelDeclineInvite(WorldPacket &recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Opcode %u", recvPacket.GetOpcode()); -} - -void WorldSession::SendPlayerNotFoundNotice(std::string name) -{ - WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, name.size()+1); - data << name; - SendPacket(&data); -} - -void WorldSession::SendPlayerAmbiguousNotice(std::string name) -{ - WorldPacket data(SMSG_CHAT_PLAYER_AMBIGUOUS, name.size()+1); - data << name; - SendPacket(&data); -} - -void WorldSession::SendWrongFactionNotice() -{ - WorldPacket data(SMSG_CHAT_WRONG_FACTION, 0); - SendPacket(&data); -} - -void WorldSession::SendChatRestrictedNotice(ChatRestrictionType restriction) -{ - WorldPacket data(SMSG_CHAT_RESTRICTED, 1); - data << uint8(restriction); - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp b/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp deleted file mode 100755 index 6693cdfca27..00000000000 --- a/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 "Log.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectAccessor.h" -#include "CreatureAI.h" -#include "ObjectDefines.h" -#include "Vehicle.h" -#include "VehicleDefines.h" - -void WorldSession::HandleAttackSwingOpcode(WorldPacket& recv_data) -{ - uint64 guid; - recv_data >> guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid)); - - Unit* pEnemy = ObjectAccessor::GetUnit(*_player, guid); - - if (!pEnemy) - { - // stop attack state at client - SendAttackStop(NULL); - return; - } - - if (!_player->IsValidAttackTarget(pEnemy)) - { - // stop attack state at client - SendAttackStop(pEnemy); - return; - } - - //! Client explicitly checks the following before sending CMSG_ATTACKSWING packet, - //! so we'll place the same check here. Note that it might be possible to reuse this snippet - //! in other places as well. - if (Vehicle* vehicle = _player->GetVehicle()) - { - VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(_player); - ASSERT(seat); - if (!(seat->m_flags & VEHICLE_SEAT_FLAG_CAN_ATTACK)) - { - SendAttackStop(pEnemy); - return; - } - } - - _player->Attack(pEnemy, true); -} - -void WorldSession::HandleAttackStopOpcode(WorldPacket & /*recv_data*/) -{ - GetPlayer()->AttackStop(); -} - -void WorldSession::HandleSetSheathedOpcode(WorldPacket& recv_data) -{ - uint32 sheathed; - recv_data >> sheathed; - - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed); - - if (sheathed >= MAX_SHEATH_STATE) - { - sLog->outError("Unknown sheath state %u ??", sheathed); - return; - } - - GetPlayer()->SetSheath(SheathState(sheathed)); -} - -void WorldSession::SendAttackStop(Unit const* enemy) -{ - WorldPacket data(SMSG_ATTACKSTOP, (8+8+4)); // we guess size - data.append(GetPlayer()->GetPackGUID()); - data.append(enemy ? enemy->GetPackGUID() : 0); // must be packed guid - data << uint32(0); // unk, can be 1 also - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/DuelHandler.cpp b/src/server/game/Server/Protocol/Handlers/DuelHandler.cpp deleted file mode 100755 index 8afd9f3b978..00000000000 --- a/src/server/game/Server/Protocol/Handlers/DuelHandler.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "Log.h" -#include "Opcodes.h" -#include "UpdateData.h" -#include "Player.h" - -void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) -{ - uint64 guid; - Player* player; - Player* plTarget; - - recvPacket >> guid; - - if (!GetPlayer()->duel) // ignore accept from duel-sender - return; - - player = GetPlayer(); - plTarget = player->duel->opponent; - - if (player == player->duel->initiator || !plTarget || player == plTarget || player->duel->startTime != 0 || plTarget->duel->startTime != 0) - return; - - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_DUEL_ACCEPTED"); - sLog->outStaticDebug("Player 1 is: %u (%s)", player->GetGUIDLow(), player->GetName()); - sLog->outStaticDebug("Player 2 is: %u (%s)", plTarget->GetGUIDLow(), plTarget->GetName()); - - time_t now = time(NULL); - player->duel->startTimer = now; - plTarget->duel->startTimer = now; - - player->SendDuelCountdown(3000); - plTarget->SendDuelCountdown(3000); -} - -void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DUEL_CANCELLED"); - uint64 guid; - recvPacket >> guid; - - // no duel requested - if (!GetPlayer()->duel) - return; - - // player surrendered in a duel using /forfeit - if (GetPlayer()->duel->startTime != 0) - { - GetPlayer()->CombatStopWithPets(true); - if (GetPlayer()->duel->opponent) - GetPlayer()->duel->opponent->CombatStopWithPets(true); - - GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg - GetPlayer()->DuelComplete(DUEL_WON); - return; - } - - GetPlayer()->DuelComplete(DUEL_INTERRUPTED); -} diff --git a/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp b/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp deleted file mode 100755 index 7d99213acf0..00000000000 --- a/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp +++ /dev/null @@ -1,1043 +0,0 @@ -/* - * 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" -#include "DB2Structure.h" -#include "DB2Stores.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 + 8); - 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) - data << uint64(0); // player who caused error (in some cases). - - SendPacket(&data); -} - -void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE"); - - BytesGuid guid; - guid.guid = 0; - - recv_data.ReadByteMask(guid.bytes[6]); - recv_data.ReadByteMask(guid.bytes[5]); - recv_data.ReadByteMask(guid.bytes[0]); - recv_data.ReadByteMask(guid.bytes[3]); - recv_data.ReadByteMask(guid.bytes[4]); - recv_data.ReadByteMask(guid.bytes[7]); - recv_data.ReadByteMask(guid.bytes[1]); - recv_data.ReadByteMask(guid.bytes[2]); - - recv_data.read_skip<uint32>(); - recv_data.read_skip<uint32>(); - - std::string membername; - recv_data >> membername; - recv_data.read_skip<uint32>(); - - recv_data.ReadByteSeq(guid.bytes[0]); - recv_data.ReadByteSeq(guid.bytes[7]); - recv_data.ReadByteSeq(guid.bytes[4]); - recv_data.ReadByteSeq(guid.bytes[1]); - recv_data.ReadByteSeq(guid.bytes[2]); - recv_data.ReadByteSeq(guid.bytes[6]); - recv_data.ReadByteSeq(guid.bytes[5]); - std::string string0; - recv_data >> string0; - recv_data.ReadByteSeq(guid.bytes[3]); - - // 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()) - 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("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("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("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 &recv_data) -{ - if (!GetPlayer()->GetGroup()) - { - recv_data.rfinish(); - return; - } - - uint64 Guid; - uint32 NumberOfPlayers; - uint8 rollType; - recv_data >> Guid; //guid of the item rolled - recv_data >> NumberOfPlayers; - recv_data >> rollType; //0: pass, 1: need, 2: greed - - //sLog->outDebug("WORLD RECIEVE CMSG_LOOT_ROLL, From:%u, Numberofplayers:%u, Choise:%u", (uint32)Guid, NumberOfPlayers, Choise); - - Group* group = GetPlayer()->GetGroup(); - if (!group) - return; - - // everything's fine, do it - group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, 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); - - // New 4.x: it is now possible to convert a raid to a group if member count is 5 or less - - bool toRaid; - recv_data >> toRaid; - - if (toRaid) - group->ConvertToRaid(); - else - group->ConvertToGroup(); -} - -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::HandleGroupSwapSubGroupOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SWAP_SUB_GROUP"); - std::string unk1; - std::string unk2; - - recv_data >> unk1; - recv_data >> unk2; -} - -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 SMSG_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(SMSG_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("CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!"); - return; - } - - GetPlayer()->SetPassOnGroupLoot(passOnLoot); -} diff --git a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp deleted file mode 100755 index fff068a0a04..00000000000 --- a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "GuildMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Guild.h" -#include "GossipDef.h" -#include "SocialMgr.h" - -// Helper for getting guild object of session's player. -// If guild does not exist, sends error (if necessary). -inline Guild* _GetPlayerGuild(WorldSession* session, bool sendError = false) -{ - if (uint32 guildId = session->GetPlayer()->GetGuildId()) // If guild id = 0, player is not in guild - if (Guild* guild = sGuildMgr->GetGuildById(guildId)) // Find guild by id - return guild; - if (sendError) - Guild::SendCommandResult(session, GUILD_CREATE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD); - return NULL; -} - -void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_QUERY"); - - uint64 guildGuid, playerGuid; - recvPacket >> guildGuid >> playerGuid; - - // If guild doesn't exist or player is not part of the guild send error - if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) - if (guild->IsMember(playerGuid)) - { - guild->HandleQuery(this); - return; - } - - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD); -} - -void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_CREATE"); - - std::string name; - recvPacket >> name; - - if (!GetPlayer()->GetGuildId()) // Player cannot be in guild - { - Guild* guild = new Guild(); - if (guild->Create(GetPlayer(), name)) - sGuildMgr->AddGuild(guild); - else - delete guild; - } -} - -void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_INVITE"); - - std::string invitedName; - recvPacket >> invitedName; - - if (normalizePlayerName(invitedName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleInviteMember(this, invitedName); -} - -void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_REMOVE"); - - std::string playerName; - recvPacket >> playerName; - - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleRemoveMember(this, playerName); -} - -void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_ACCEPT"); - // Player cannot be in guild - if (!GetPlayer()->GetGuildId()) - // Guild where player was invited must exist - if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildIdInvited())) - guild->HandleAcceptMember(this); -} - -void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_DECLINE"); - - GetPlayer()->SetGuildIdInvited(0); - GetPlayer()->SetInGuild(0); -} - -void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_INFO"); - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->SendInfo(this); -} - -void WorldSession::HandleGuildRosterOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_ROSTER"); - - BitStream mask = recvPacket.ReadBitStream(8); - - ByteBuffer bytes(8, true); - - recvPacket.ReadXorByte(mask[0], bytes[7]); - recvPacket.ReadXorByte(mask[5], bytes[4]); - recvPacket.ReadXorByte(mask[4], bytes[5]); - recvPacket.ReadXorByte(mask[7], bytes[0]); - recvPacket.ReadXorByte(mask[3], bytes[1]); - recvPacket.ReadXorByte(mask[2], bytes[2]); - recvPacket.ReadXorByte(mask[1], bytes[6]); - recvPacket.ReadXorByte(mask[6], bytes[3]); - - uint64 guildGuid = BitConverter::ToUInt64(bytes); - - if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) - if (guild->IsMember(GetPlayer()->GetGUID())) - guild->HandleRoster(this); -} - -void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_PROMOTE"); - - std::string playerName; - recvPacket >> playerName; - - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleUpdateMemberRank(this, playerName, false); -} - -void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_DEMOTE"); - - std::string playerName; - recvPacket >> playerName; - - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleUpdateMemberRank(this, playerName, true); -} - -void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_LEAVE"); - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleLeaveMember(this); -} - -void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_DISBAND"); - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleDisband(this); -} - -void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_LEADER"); - - std::string name; - recvPacket >> name; - - if (normalizePlayerName(name)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetLeader(this, name); -} - -void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_MOTD"); - - std::string motd; // Empty by default - if (!recvPacket.empty()) - recvPacket >> motd; - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetMOTD(this, motd); -} - -void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE"); - - std::string playerName; - recvPacket >> playerName; - - std::string publicNote; - recvPacket >> publicNote; - - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetMemberNote(this, playerName, publicNote, false); -} - -void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE"); - - std::string playerName; - recvPacket >> playerName; - - std::string officerNote; - recvPacket >> officerNote; - - if (normalizePlayerName(playerName)) - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetMemberNote(this, playerName, officerNote, true); -} - -void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_RANK"); - - Guild* guild = _GetPlayerGuild(this, true); - if (!guild) - { - recvPacket.rpos(recvPacket.wpos()); - return; - } - - uint32 rankId; - recvPacket >> rankId; - - uint32 rights; - recvPacket >> rights; - - std::string rankName; - recvPacket >> rankName; - - uint32 money; - recvPacket >> money; - - GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS); - for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId) - { - uint32 bankRights; - uint32 slots; - - recvPacket >> bankRights; - recvPacket >> slots; - - rightsAndSlots[tabId] = GuildBankRightsAndSlots(uint8(bankRights), slots); - } - - guild->HandleSetRankInfo(this, rankId, rankName, rights, money, rightsAndSlots); -} - -void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_ADD_RANK"); - - std::string rankName; - recvPacket >> rankName; - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleAddNewRank(this, rankName); -} - -void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_DEL_RANK"); - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleRemoveLowestRank(this); -} - -void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GUILD_INFO_TEXT"); - - std::string info; - recvPacket >> info; - - if (Guild* guild = _GetPlayerGuild(this, true)) - guild->HandleSetInfo(this, info); -} - -void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_SAVE_GUILD_EMBLEM"); - - uint64 vendorGuid; - recvPacket >> vendorGuid; - - EmblemInfo emblemInfo; - emblemInfo.ReadPacket(recvPacket); - - if (GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_TABARDDESIGNER)) - { - // Remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (Guild* guild = _GetPlayerGuild(this)) - guild->HandleSetEmblem(this, emblemInfo); - else - // "You are not part of a guild!"; - Guild::SendSaveEmblemResult(this, ERR_GUILDEMBLEM_NOGUILD); - } - else - { - // "That's not an emblem vendor!" - Guild::SendSaveEmblemResult(this, ERR_GUILDEMBLEM_INVALIDVENDOR); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleSaveGuildEmblemOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid)); - } -} - -void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_EVENT_LOG_QUERY)"); - - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendEventLog(this); -} - -void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recv_data */) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)"); - - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendMoneyInfo(this); -} - -void WorldSession::HandleGuildPermissions(WorldPacket& /* recv_data */) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_PERMISSIONS)"); - - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendPermissions(this); -} - -// Called when clicking on Guild bank gameobject -void WorldSession::HandleGuildBankerActivate(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - uint8 unk; - recv_data >> unk; - - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - { - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendBankTabsInfo(this); - else - Guild::SendCommandResult(this, GUILD_UNK1, ERR_GUILD_PLAYER_NOT_IN_GUILD); - } -} - -// Called when opening guild bank tab only (first one) -void WorldSession::HandleGuildBankQueryTab(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - uint8 tabId; - recv_data >> tabId; - - uint8 unk1; - recv_data >> unk1; - - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendBankTabData(this, tabId); -} - -void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - uint32 money; - recv_data >> money; - - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - if (money && GetPlayer()->HasEnoughMoney(money)) - if (Guild* guild = _GetPlayerGuild(this)) - guild->HandleMemberDepositMoney(this, money); -} - -void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - uint32 money; - recv_data >> money; - - if (money) - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - if (Guild* guild = _GetPlayerGuild(this)) - guild->HandleMemberWithdrawMoney(this, money); -} - -void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - { - recv_data.rfinish(); // Prevent additional spam at rejected packet - return; - } - - Guild* guild = _GetPlayerGuild(this); - if (!guild) - { - recv_data.rfinish(); // Prevent additional spam at rejected packet - return; - } - - uint8 bankToBank; - recv_data >> bankToBank; - - uint8 tabId; - uint8 slotId; - uint32 itemEntry; - uint32 splitedAmount = 0; - - if (bankToBank) - { - uint8 destTabId; - recv_data >> destTabId; - - uint8 destSlotId; - recv_data >> destSlotId; - recv_data.read_skip<uint32>(); // Always 0 - - recv_data >> tabId; - recv_data >> slotId; - recv_data >> itemEntry; - recv_data.read_skip<uint8>(); // Always 0 - - recv_data >> splitedAmount; - - guild->SwapItems(GetPlayer(), tabId, slotId, destTabId, destSlotId, splitedAmount); - } - else - { - uint8 playerBag = NULL_BAG; - uint8 playerSlotId = NULL_SLOT; - uint8 toChar = 1; - - recv_data >> tabId; - recv_data >> slotId; - recv_data >> itemEntry; - - uint8 autoStore; - recv_data >> autoStore; - if (autoStore) - { - recv_data.read_skip<uint32>(); // autoStoreCount - recv_data.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char) - recv_data.read_skip<uint32>(); // Always 0 - } - else - { - recv_data >> playerBag; - recv_data >> playerSlotId; - recv_data >> toChar; - recv_data >> splitedAmount; - } - - // Player <-> Bank - // Allow to work with inventory only - if (!Player::IsInventoryPos(playerBag, playerSlotId) && !(playerBag == NULL_BAG && playerSlotId == NULL_SLOT)) - GetPlayer()->SendEquipError(EQUIP_ERR_NONE, NULL); - else - guild->SwapItemsWithInventory(GetPlayer(), toChar, tabId, slotId, playerBag, playerSlotId, splitedAmount); - } -} - -void WorldSession::HandleGuildBankBuyTab(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - uint8 tabId; - recv_data >> tabId; - - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - if (Guild* guild = _GetPlayerGuild(this)) - guild->HandleBuyBankTab(this, tabId); -} - -void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)"); - - uint64 GoGuid; - recv_data >> GoGuid; - - uint8 tabId; - recv_data >> tabId; - - std::string name; - recv_data >> name; - - std::string icon; - recv_data >> icon; - - if (!name.empty() && !icon.empty()) - if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - if (Guild* guild = _GetPlayerGuild(this)) - guild->HandleSetBankTabInfo(this, tabId, name, icon); -} - -void WorldSession::HandleGuildBankLogQuery(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)"); - - uint8 tabId; - recv_data >> tabId; - - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendBankLog(this, tabId); -} - -void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_QUERY_GUILD_BANK_TEXT"); - - uint8 tabId; - recv_data >> tabId; - - if (Guild* guild = _GetPlayerGuild(this)) - guild->SendBankTabText(this, tabId); -} - -void WorldSession::HandleSetGuildBankTabText(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_GUILD_BANK_TEXT"); - - uint8 tabId; - recv_data >> tabId; - - std::string text; - recv_data >> text; - - if (Guild* guild = _GetPlayerGuild(this)) - guild->SetBankTabText(tabId, text); -} diff --git a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp deleted file mode 100755 index 2146b8a89bb..00000000000 --- a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp +++ /dev/null @@ -1,1444 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "Item.h" -#include "UpdateData.h" -#include "ObjectAccessor.h" -#include "SpellInfo.h" - -void WorldSession::HandleSplitItemOpcode(WorldPacket & recv_data) -{ - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_SPLIT_ITEM"); - uint8 srcbag, srcslot, dstbag, dstslot; - uint32 count; - - recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; - //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); - - uint16 src = ((srcbag << 8) | srcslot); - uint16 dst = ((dstbag << 8) | dstslot); - - if (src == dst) - return; - - if (count == 0) - return; //check count - if zero it's fake packet - - if (!_player->IsValidPos(srcbag, srcslot, true)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (!_player->IsValidPos(dstbag, dstslot, false)) // can be autostore pos - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - _player->SplitItem(src, dst, count); -} - -void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recv_data) -{ - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_SWAP_INV_ITEM"); - uint8 srcslot, dstslot; - - recv_data >> dstslot >> srcslot; - //sLog->outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot); - - // prevent attempt swap same item to current position generated by client at special checting sequence - if (srcslot == dstslot) - return; - - if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, true)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - - _player->SwapItem(src, dst); -} - -void WorldSession::HandleAutoEquipItemSlotOpcode(WorldPacket & recv_data) -{ - uint64 itemguid; - uint8 dstslot; - recv_data >> itemguid >> dstslot; - - // cheating attempt, client should never send opcode in that case - if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot)) - return; - - Item* item = _player->GetItemByGuid(itemguid); - uint16 dstpos = dstslot | (INVENTORY_SLOT_BAG_0 << 8); - - if (!item || item->GetPos() == dstpos) - return; - - _player->SwapItem(item->GetPos(), dstpos); -} - -void WorldSession::HandleSwapItem(WorldPacket & recv_data) -{ - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_SWAP_ITEM"); - uint8 dstbag, dstslot, srcbag, srcslot; - - recv_data >> dstbag >> dstslot >> srcbag >> srcslot ; - //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot); - - uint16 src = ((srcbag << 8) | srcslot); - uint16 dst = ((dstbag << 8) | dstslot); - - // prevent attempt swap same item to current position generated by client at special checting sequence - if (src == dst) - return; - - if (!_player->IsValidPos(srcbag, srcslot, true)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (!_player->IsValidPos(dstbag, dstslot, true)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - _player->SwapItem(src, dst); -} - -void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recv_data) -{ - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_AUTOEQUIP_ITEM"); - uint8 srcbag, srcslot; - - recv_data >> srcbag >> srcslot; - //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); - - Item* pSrcItem = _player->GetItemByPos(srcbag, srcslot); - if (!pSrcItem) - return; // only at cheat - - uint16 dest; - InventoryResult msg = _player->CanEquipItem(NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag()); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pSrcItem, NULL); - return; - } - - uint16 src = pSrcItem->GetPos(); - if (dest == src) // prevent equip in same slot, only at cheat - return; - - Item* pDstItem = _player->GetItemByPos(dest); - if (!pDstItem) // empty slot, simple case - { - _player->RemoveItem(srcbag, srcslot, true); - _player->EquipItem(dest, pSrcItem, true); - _player->AutoUnequipOffhandIfNeed(); - } - else // have currently equipped item, not simple case - { - uint8 dstbag = pDstItem->GetBagSlot(); - uint8 dstslot = pDstItem->GetSlot(); - - msg = _player->CanUnequipItem(dest, !pSrcItem->IsBag()); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pDstItem, NULL); - return; - } - - // check dest->src move possibility - ItemPosCountVec sSrc; - uint16 eSrc = 0; - if (_player->IsInventoryPos(src)) - { - msg = _player->CanStoreItem(srcbag, srcslot, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanStoreItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); - } - else if (_player->IsBankPos(src)) - { - msg = _player->CanBankItem(srcbag, srcslot, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanBankItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); - } - else if (_player->IsEquipmentPos(src)) - { - msg = _player->CanEquipItem(srcslot, eSrc, pDstItem, true); - if (msg == EQUIP_ERR_OK) - msg = _player->CanUnequipItem(eSrc, true); - } - - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pDstItem, pSrcItem); - return; - } - - // now do moves, remove... - _player->RemoveItem(dstbag, dstslot, false); - _player->RemoveItem(srcbag, srcslot, false); - - // add to dest - _player->EquipItem(dest, pSrcItem, true); - - // add to src - if (_player->IsInventoryPos(src)) - _player->StoreItem(sSrc, pDstItem, true); - else if (_player->IsBankPos(src)) - _player->BankItem(sSrc, pDstItem, true); - else if (_player->IsEquipmentPos(src)) - _player->EquipItem(eSrc, pDstItem, true); - - _player->AutoUnequipOffhandIfNeed(); - } -} - -void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data) -{ - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_DESTROYITEM"); - uint8 bag, slot, count, data1, data2, data3; - - recv_data >> bag >> slot >> count >> data1 >> data2 >> data3; - //sLog->outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count); - - uint16 pos = (bag << 8) | slot; - - // prevent drop unequipable items (in combat, for example) and non-empty bags - if (_player->IsEquipmentPos(pos) || _player->IsBagPos(pos)) - { - InventoryResult msg = _player->CanUnequipItem(pos, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, _player->GetItemByPos(pos), NULL); - return; - } - } - - Item* pItem = _player->GetItemByPos(bag, slot); - if (!pItem) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (pItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_INDESTRUCTIBLE) - { - _player->SendEquipError(EQUIP_ERR_CANT_DROP_SOULBOUND, NULL, NULL); - return; - } - - if (count) - { - uint32 i_count = count; - _player->DestroyItemCount(pItem, i_count, true); - } - else - _player->DestroyItem(bag, slot, true); -} - -// Only _static_ data send in this packet !!! -void WorldSession::HandleItemQuerySingleOpcode(WorldPacket & recv_data) -{ - uint32 count, type; - recv_data >> count >> type; - - if (type != DB2_REPLY_SPARSE && type != DB2_REPLY_ITEM) - return; - - for (uint32 i = 0; i < count; ++i) - { - uint32 item; - recv_data >> item; - recv_data.read_skip<uint64>(); - WorldPacket data2(SMSG_DB_REPLY, 700); - ByteBuffer data; - data2 << uint32(type); - data2 << uint32(item); - - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); - if (proto) - { - data << uint32(item); - if (type == DB2_REPLY_ITEM) - { - data << uint32(proto->Class); - data << uint32(proto->SubClass); - data << int32(proto->Unk0); - data << uint32(proto->Material); - data << uint32(proto->DisplayInfoID); - data << uint32(proto->InventoryType); - data << uint32(proto->Sheath); - } - else if (type == DB2_REPLY_SPARSE) - { - data << uint32(proto->Quality); - data << uint32(proto->Flags); - data << uint32(proto->Flags2); - data << int32(proto->BuyPrice); - data << uint32(proto->SellPrice); - data << uint32(proto->InventoryType); - data << int32(proto->AllowableClass); - data << int32(proto->AllowableRace); - data << uint32(proto->ItemLevel); - data << uint32(proto->RequiredLevel); - data << uint32(proto->RequiredSkill); - data << uint32(proto->RequiredSkillRank); - data << uint32(proto->RequiredSpell); - data << uint32(proto->RequiredHonorRank); - data << uint32(proto->RequiredCityRank); - data << uint32(proto->RequiredReputationFaction); - data << uint32(proto->RequiredReputationRank); - data << int32(proto->MaxCount); - data << int32(proto->Stackable); - data << uint32(proto->ContainerSlots); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - data << uint32(proto->ItemStat[x].ItemStatType); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - data << int32(proto->ItemStat[x].ItemStatValue); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - data << int32(proto->ItemStat[x].ItemStatUnk1); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - data << int32(proto->ItemStat[x].ItemStatUnk2); - - data << uint32(proto->ScalingStatDistribution); - data << uint32(proto->DamageType); - data << uint32(proto->Delay); - data << float(proto->RangedModRange); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - data << int32(proto->Spells[x].SpellId); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - data << uint32(proto->Spells[x].SpellTrigger); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - data << int32(proto->Spells[x].SpellCharges); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - data << int32(proto->Spells[x].SpellCooldown); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - data << uint32(proto->Spells[x].SpellCategory); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - data << int32(proto->Spells[x].SpellCategoryCooldown); - - data << uint32(proto->Bonding); - - // item name - std::string name = proto->Name1; - data << uint16(name.length() + 1); - data << name; - - for (uint32 i = 0; i < 3; ++i) // other 3 names - data << uint16(0); - - std::string desc = proto->Description; - data << uint16(desc.length() + 1); - data << desc; - - data << uint32(proto->PageText); - data << uint32(proto->LanguageID); - data << uint32(proto->PageMaterial); - data << uint32(proto->StartQuest); - data << uint32(proto->LockID); - data << int32(proto->Material); - data << uint32(proto->Sheath); - data << int32(proto->RandomProperty); - data << int32(proto->RandomSuffix); - data << uint32(proto->ItemSet); - data << uint32(proto->MaxDurability); - - data << uint32(proto->Area); - data << uint32(proto->Map); - data << uint32(proto->BagFamily); - data << uint32(proto->TotemCategory); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x) - data << uint32(proto->Socket[x].Color); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x) - data << uint32(proto->Socket[x].Content); - - data << uint32(proto->socketBonus); - data << uint32(proto->GemProperties); - data << float(proto->ArmorDamageModifier); - data << int32(proto->Duration); - data << uint32(proto->ItemLimitCategory); - data << uint32(proto->HolidayId); - data << float(proto->StatScalingFactor); // StatScalingFactor - data << uint32(proto->Field130); // archaeology unk - data << uint32(proto->Field131); // archaeology findinds count - } - else - { - data << uint32(item | 0x80000000); // sometimes with | 0x80000000 - data << uint32(0); - } - - data2 << uint32(data.size()); - data2.append(data); - } - - data2 << uint32(type); - _player->GetSession()->SendPacket(&data2); - } -} - -void WorldSession::HandleReadItem(WorldPacket & recv_data) -{ - uint8 bag, slot; - recv_data >> bag >> slot; - - Item* pItem = _player->GetItemByPos(bag, slot); - - if (pItem && pItem->GetTemplate()->PageText) - { - WorldPacket data; - - InventoryResult msg = _player->CanUseItem(pItem); - if (msg == EQUIP_ERR_OK) - { - data.Initialize(SMSG_READ_ITEM_OK, 8); - sLog->outDetail("STORAGE: Item page sent"); - } - else - { - data.Initialize(SMSG_READ_ITEM_FAILED, 8); - sLog->outDetail("STORAGE: Unable to read item"); - _player->SendEquipError(msg, pItem, NULL); - } - data << pItem->GetGUID(); - SendPacket(&data); - } - else - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); -} - -void WorldSession::HandlePageQuerySkippedOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY"); - - uint32 itemid; - uint64 guid; - - recv_data >> itemid >> guid; - - sLog->outDetail("Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u", - itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid)); -} - -void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SELL_ITEM"); - uint64 vendorguid, itemguid; - uint32 count; - - recv_data >> vendorguid >> itemguid >> count; - - if (!itemguid) - return; - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Item* pItem = _player->GetItemByGuid(itemguid); - if (pItem) - { - // prevent sell not owner item - if (_player->GetGUID() != pItem->GetOwnerGUID()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); - return; - } - - // prevent sell non empty bag by drag-and-drop at vendor's item list - if (pItem->IsNotEmptyBag()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); - return; - } - - // prevent sell currently looted item - if (_player->GetLootGUID() == pItem->GetGUID()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); - return; - } - - // prevent selling item for sellprice when the item is still refundable - // this probably happens when right clicking a refundable item, the client sends both - // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified) - if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) - return; // Therefore, no feedback to client - - // special case at auto sell (sell all) - if (count == 0) - { - count = pItem->GetCount(); - } - else - { - // prevent sell more items that exist in stack (possible only not from client) - if (count > pItem->GetCount()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); - return; - } - } - - ItemTemplate const* pProto = pItem->GetTemplate(); - if (pProto) - { - if (pProto->SellPrice > 0) - { - if (count < pItem->GetCount()) // need split items - { - Item* pNewItem = pItem->CloneItem(count, _player); - if (!pNewItem) - { - sLog->outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count); - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); - return; - } - - pItem->SetCount(pItem->GetCount() - count); - _player->ItemRemovedQuestCheck(pItem->GetEntry(), count); - if (_player->IsInWorld()) - pItem->SendUpdateToPlayer(_player); - pItem->SetState(ITEM_CHANGED, _player); - - _player->AddItemToBuyBackSlot(pNewItem); - if (_player->IsInWorld()) - pNewItem->SendUpdateToPlayer(_player); - } - else - { - _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); - pItem->RemoveFromUpdateQueueOf(_player); - _player->AddItemToBuyBackSlot(pItem); - } - - uint32 money = pProto->SellPrice * count; - _player->ModifyMoney(money); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); - } - else - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); - return; - } - } - _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid, 0); - return; -} - -void WorldSession::HandleBuybackItem(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUYBACK_ITEM"); - uint64 vendorguid; - uint32 slot; - - recv_data >> vendorguid >> slot; - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Item* pItem = _player->GetItemFromBuyBackSlot(slot); - if (pItem) - { - uint32 price = _player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START); - if (!_player->HasEnoughMoney(price)) - { - _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, pItem->GetEntry(), 0); - return; - } - - ItemPosCountVec dest; - InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg == EQUIP_ERR_OK) - { - _player->ModifyMoney(-(int32)price); - _player->RemoveItemFromBuyBackSlot(slot, false); - _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); - _player->StoreItem(dest, pItem, true); - } - else - _player->SendEquipError(msg, pItem, NULL); - return; - } - else - _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, 0, 0); -} - -void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUY_ITEM_IN_SLOT"); - uint64 vendorguid, bagguid; - uint32 item, slot, count; - uint8 bagslot; - - recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; - - // client expects count starting at 1, and we send vendorslot+1 to client already - if (slot > 0) - --slot; - else - return; // cheating - - uint8 bag = NULL_BAG; // init for case invalid bagGUID - - // find bag slot by bag guid - if (bagguid == _player->GetGUID()) - bag = INVENTORY_SLOT_BAG_0; - else - { - for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) - { - if (Bag* pBag = _player->GetBagByPos(i)) - { - if (bagguid == pBag->GetGUID()) - { - bag = i; - break; - } - } - } - } - - // bag not found, cheating? - if (bag == NULL_BAG) - return; - - GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagslot); -} - -void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUY_ITEM"); - uint64 vendorguid, unk2; // unk2 can be 0? - uint32 item, slot, count; - uint8 unk1; // if this is == 2 then the count might be multiplied by 100 - int8 unk3; // only known value = -1, according to the client it can take more values - - recv_data >> vendorguid >> unk1 >> item >> slot >> count >> unk2 >> unk3; - - // client expects count starting at 1, and we send vendorslot+1 to client already - if (slot > 0) - --slot; - else - return; // cheating - - GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, NULL_BAG, NULL_SLOT); -} - -void WorldSession::HandleListInventoryOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - - if (!GetPlayer()->isAlive()) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LIST_INVENTORY"); - - SendListInventory(guid); -} - -void WorldSession::SendListInventory(uint64 vendorGuid) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LIST_INVENTORY"); - - Creature* vendor = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR); - if (!vendor) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid))); - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // Stop the npc if moving - if (vendor->HasUnitState(UNIT_STAT_MOVING)) - vendor->StopMoving(); - - uint8* bytes = (uint8*)&vendorGuid; - - VendorItemData const* items = vendor->GetVendorItems(); - if (!items) - { - WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1); - data.WriteByteMask(bytes[5]); - data.WriteByteMask(bytes[6]); - data.WriteByteMask(bytes[1]); - data.WriteByteMask(bytes[2]); - data.WriteByteMask(bytes[3]); - data.WriteByteMask(bytes[0]); - data.WriteByteMask(bytes[7]); - data.WriteByteMask(bytes[4]); - - data.WriteByteSeq(bytes[2]); - data.WriteByteSeq(bytes[3]); - - data << uint8(0); // count == 0, next will be error code - data << uint8(0xA0); // Only seen 0xA0 (160) so far ( should we send 0 here?) - - data.WriteByteSeq(bytes[4]); - data.WriteByteSeq(bytes[7]); - data.WriteByteSeq(bytes[6]); - SendPacket(&data); - return; - } - - uint8 itemCount = items->GetItemCount(); - uint8 count = 0; - - WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4); - - data.WriteByteMask(bytes[5]); - data.WriteByteMask(bytes[6]); - data.WriteByteMask(bytes[1]); - data.WriteByteMask(bytes[2]); - data.WriteByteMask(bytes[3]); - data.WriteByteMask(bytes[0]); - data.WriteByteMask(bytes[7]); - data.WriteByteMask(bytes[4]); - - data.WriteByteSeq(bytes[2]); - data.WriteByteSeq(bytes[3]); - - size_t countPos = data.wpos(); - data << uint32(count); - - data.WriteByteSeq(bytes[5]); - data.WriteByteSeq(bytes[0]); - data.WriteByteSeq(bytes[1]); - - data << uint8(0xA0); // Only seen 0xA0 (160) so far - - data.WriteByteSeq(bytes[4]); - data.WriteByteSeq(bytes[7]); - data.WriteByteSeq(bytes[6]); - - - float discountMod = _player->GetReputationPriceDiscount(vendor); - - for (uint8 slot = 0; slot < itemCount; ++slot) - { - if (VendorItem const* item = items->GetItem(slot)) - { - if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item->item)) - { - if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster()) - continue; - // Only display items in vendor lists for the team the - // player is on. If GM on, display all items. - if (!_player->isGameMaster() && ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE))) - continue; - - // Items sold out are not displayed in list - uint32 leftInStock = !item->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(item); - if (!_player->isGameMaster() && !leftInStock) - continue; - - ++count; - - // reputation discount - int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; - - data << uint32(itemTemplate->MaxDurability); - data << uint32(slot + 1); // client expects counting to start at 1 - data << uint32(item->item); - data << uint32(0); // Always 0? - data << uint32(itemTemplate->DisplayInfoID); - data << int32(leftInStock); - data << uint32(itemTemplate->BuyCount); - data << uint32(item->ExtendedCost); - data << uint32(1); // Always 1? - data << uint32(price); - } - } - } - - if (count == 0) - { - SendPacket(&data); - return; - } - - data.put<uint32>(countPos, count); - SendPacket(&data); -} - -void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket & recv_data) -{ - //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_AUTOSTORE_BAG_ITEM"); - uint8 srcbag, srcslot, dstbag; - - recv_data >> srcbag >> srcslot >> dstbag; - //sLog->outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag); - - Item* pItem = _player->GetItemByPos(srcbag, srcslot); - if (!pItem) - return; - - if (!_player->IsValidPos(dstbag, NULL_SLOT, false)) // can be autostore pos - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - uint16 src = pItem->GetPos(); - - // check unequip potability for equipped items and bank bags - if (_player->IsEquipmentPos (src) || _player->IsBagPos (src)) - { - InventoryResult msg = _player->CanUnequipItem(src, !_player->IsBagPos (src)); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - } - - ItemPosCountVec dest; - InventoryResult msg = _player->CanStoreItem(dstbag, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - // no-op: placed in same slot - if (dest.size() == 1 && dest[0].pos == src) - { - // just remove grey item state - _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->StoreItem(dest, pItem, true); -} - -void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_BUY_BANK_SLOT"); - - uint64 guid; - recvPacket >> guid; - - // cheating protection - /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command. - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); - if (!creature) - { - sLog->outDebug("WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - */ - - uint32 slot = _player->GetBankBagSlotCount(); - - // next slot - ++slot; - - sLog->outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot); - - BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot); - - WorldPacket data(SMSG_BUY_BANK_SLOT_RESULT, 4); - - if (!slotEntry) - { - data << uint32(ERR_BANKSLOT_FAILED_TOO_MANY); - SendPacket(&data); - return; - } - - uint32 price = slotEntry->price; - - if (!_player->HasEnoughMoney(price)) - { - data << uint32(ERR_BANKSLOT_INSUFFICIENT_FUNDS); - SendPacket(&data); - return; - } - - _player->SetBankBagSlotCount(slot); - _player->ModifyMoney(-int32(price)); - - data << uint32(ERR_BANKSLOT_OK); - SendPacket(&data); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT); -} - -void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOBANK_ITEM"); - uint8 srcbag, srcslot; - - recvPacket >> srcbag >> srcslot; - sLog->outDebug(LOG_FILTER_NETWORKIO, "STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); - - Item* pItem = _player->GetItemByPos(srcbag, srcslot); - if (!pItem) - return; - - ItemPosCountVec dest; - InventoryResult msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - if (dest.size() == 1 && dest[0].pos == pItem->GetPos()) - { - _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - _player->BankItem(dest, pItem, true); -} - -void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOSTORE_BANK_ITEM"); - uint8 srcbag, srcslot; - - recvPacket >> srcbag >> srcslot; - sLog->outDebug(LOG_FILTER_NETWORKIO, "STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); - - Item* pItem = _player->GetItemByPos(srcbag, srcslot); - if (!pItem) - return; - - if (_player->IsBankPos(srcbag, srcslot)) // moving from bank to inventory - { - ItemPosCountVec dest; - InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->StoreItem(dest, pItem, true); - _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - } - else // moving from inventory to bank - { - ItemPosCountVec dest; - InventoryResult msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->BankItem(dest, pItem, true); - } -} - -void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster, uint32 ItemID, uint32 SpellID) -{ - WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10 - data << uint64(Target); - data << uint64(Caster); - data << uint32(ItemID); - data << uint32(SpellID); - data << uint8(0); - SendPacket(&data); -} - -void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid, uint32 slot, uint32 Duration) -{ - // last check 2.0.10 - WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8)); - data << uint64(Itemguid); - data << uint32(slot); - data << uint32(Duration); - data << uint64(Playerguid); - SendPacket(&data); -} - -void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) -{ - uint32 itemid; - recv_data >> itemid; - recv_data.read_skip<uint64>(); // guid - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_NAME_QUERY %u", itemid); - ItemSetNameEntry const* pName = sObjectMgr->GetItemSetNameEntry(itemid); - if (pName) - { - std::string Name = pName->name; - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - if (ItemSetNameLocale const* isnl = sObjectMgr->GetItemSetNameLocale(itemid)) - ObjectMgr::GetLocaleString(isnl->Name, loc_idx, Name); - - WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+Name.size()+1+4)); - data << uint32(itemid); - data << Name; - data << uint32(pName->InventoryType); - SendPacket(&data); - } -} - -void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_WRAP_ITEM"); - - uint8 gift_bag, gift_slot, item_bag, item_slot; - - recv_data >> gift_bag >> gift_slot; // paper - recv_data >> item_bag >> item_slot; // item - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot); - - Item* gift = _player->GetItemByPos(gift_bag, gift_slot); - if (!gift) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); - return; - } - - if (!(gift->GetTemplate()->Flags & ITEM_PROTO_FLAG_WRAPPER)) // cheating: non-wrapper wrapper - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); - return; - } - - Item* item = _player->GetItemByPos(item_bag, item_slot); - - if (!item) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL); - return; - } - - if (item == gift) // not possable with pacjket from real client - { - _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->IsEquipped()) - { - _player->SendEquipError(EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); - { - _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->IsBag()) - { - _player->SendEquipError(EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->IsSoulBound()) - { - _player->SendEquipError(EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->GetMaxStackCount() != 1) - { - _player->SendEquipError(EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL); - return; - } - - // maybe not correct check (it is better than nothing) - if (item->GetTemplate()->MaxCount>0) - { - _player->SendEquipError(EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL); - return; - } - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS)); - item->SetEntry(gift->GetEntry()); - - switch (item->GetEntry()) - { - case 5042: item->SetEntry(5043); break; - case 5048: item->SetEntry(5044); break; - case 17303: item->SetEntry(17302); break; - case 17304: item->SetEntry(17305); break; - case 17307: item->SetEntry(17308); break; - case 21830: item->SetEntry(21831); break; - } - item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); - item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED); - item->SetState(ITEM_CHANGED, _player); - - if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance` - { - // after save it will be impossible to remove the item from the queue - item->RemoveFromUpdateQueueOf(_player); - item->SaveToDB(trans); // item gave inventory record unchanged and can be save standalone - } - CharacterDatabase.CommitTransaction(trans); - - uint32 count = 1; - _player->DestroyItemCount(gift, count, true); -} - -void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SOCKET_GEMS"); - - uint64 item_guid; - uint64 gem_guids[MAX_GEM_SOCKETS]; - - recv_data >> item_guid; - if (!item_guid) - return; - - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - recv_data >> gem_guids[i]; - - //cheat -> tried to socket same gem multiple times - if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) || - (gem_guids[1] && (gem_guids[1] == gem_guids[2]))) - return; - - Item* itemTarget = _player->GetItemByGuid(item_guid); - if (!itemTarget) //missing item to socket - return; - - ItemTemplate const* itemProto = itemTarget->GetTemplate(); - if (!itemProto) - return; - - //this slot is excepted when applying / removing meta gem bonus - uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT); - - Item* Gems[MAX_GEM_SOCKETS]; - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL; - - GemPropertiesEntry const* GemProps[MAX_GEM_SOCKETS]; - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage - GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetTemplate()->GemProperties) : NULL; - - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe - { - if (!GemProps[i]) - continue; - - // tried to put gem in socket where no socket exists (take care about prismatic sockets) - if (!itemProto->Socket[i].Color) - { - // no prismatic socket - if (!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) - return; - - // not first not-colored (not normaly used) socket - if (i != 0 && !itemProto->Socket[i-1].Color && (i+1 >= MAX_GEM_SOCKETS || itemProto->Socket[i+1].Color)) - return; - - // ok, this is first not colored socket for item with prismatic socket - } - - // tried to put normal gem in meta socket - if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META) - return; - - // tried to put meta gem in normal socket - if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META) - return; - } - - uint32 GemEnchants[MAX_GEM_SOCKETS]; - uint32 OldEnchants[MAX_GEM_SOCKETS]; - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get new and old enchantments - { - GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; - OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i)); - } - - // check unique-equipped conditions - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - { - if (!Gems[i]) - continue; - - // continue check for case when attempt add 2 similar unique equipped gems in one item. - ItemTemplate const* iGemProto = Gems[i]->GetTemplate(); - - // unique item (for new and already placed bit removed enchantments - if (iGemProto->Flags & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) - { - for (int j = 0; j < MAX_GEM_SOCKETS; ++j) - { - if (i == j) // skip self - continue; - - if (Gems[j]) - { - if (iGemProto->ItemId == Gems[j]->GetEntry()) - { - _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); - return; - } - } - else if (OldEnchants[j]) - { - if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) - { - if (iGemProto->ItemId == enchantEntry->GemID) - { - _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); - return; - } - } - } - - } - } - - // unique limit type item - int32 limit_newcount = 0; - if (iGemProto->ItemLimitCategory) - { - if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory)) - { - // NOTE: limitEntry->mode is not checked because if item has limit then it is applied in equip case - for (int j = 0; j < MAX_GEM_SOCKETS; ++j) - { - if (Gems[j]) - { - // new gem - if (iGemProto->ItemLimitCategory == Gems[j]->GetTemplate()->ItemLimitCategory) - ++limit_newcount; - } - else if (OldEnchants[j]) - { - // existing gem - if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) - if (ItemTemplate const* jProto = sObjectMgr->GetItemTemplate(enchantEntry->GemID)) - if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory) - ++limit_newcount; - } - } - - if (limit_newcount > 0 && uint32(limit_newcount) > limitEntry->maxCount) - { - _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); - return; - } - } - } - - // for equipped item check all equipment for duplicate equipped gems - if (itemTarget->IsEquipped()) - { - if (InventoryResult res = _player->CanEquipUniqueItem(Gems[i], slot, std::max(limit_newcount, 0))) - { - _player->SendEquipError(res, itemTarget, NULL); - return; - } - } - } - - bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus - _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item) - - //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met - - //remove ALL enchants - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot) - _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), false); - - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - { - if (GemEnchants[i]) - { - itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0); - if (Item* guidItem = _player->GetItemByGuid(gem_guids[i])) - _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true); - } - } - - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) - _player->ApplyEnchantment(itemTarget, EnchantmentSlot(enchant_slot), true); - - bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state - if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... - { - _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->socketBonus : 0), 0, 0); - _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true); - //it is not displayed, client has an inbuilt system to determine if the bonus is activated - } - - _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item) - - itemTarget->ClearSoulboundTradeable(_player); // clear tradeable flag -} - -void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT"); - - uint32 slot; - - recv_data >> slot; - - // apply only to equipped item - if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot)) - return; - - Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - - if (!item) - return; - - if (!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) - return; - - GetPlayer()->ApplyEnchantment(item, TEMP_ENCHANTMENT_SLOT, false); - item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); -} - -void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_REFUND_INFO"); - - uint64 guid; - recv_data >> guid; // item guid - - Item* item = _player->GetItemByGuid(guid); - if (!item) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Item refund: item not found!"); - return; - } - - GetPlayer()->SendRefundInfo(item); -} - -void WorldSession::HandleItemRefund(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_REFUND"); - uint64 guid; - recv_data >> guid; // item guid - - Item* item = _player->GetItemByGuid(guid); - if (!item) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Item refund: item not found!"); - return; - } - - GetPlayer()->RefundItem(item); -} - -/** - * Handles the packet sent by the client when requesting information about item text. - * - * This function is called when player clicks on item which has some flag set - */ -void WorldSession::HandleItemTextQuery(WorldPacket & recv_data ) -{ - uint64 itemGuid; - recv_data >> itemGuid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid)); - - WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, 14); // guess size - - if (Item* item = _player->GetItemByGuid(itemGuid)) - { - data << uint8(0); // has text - data << uint64(itemGuid); // item guid - data << item->GetText(); - } - else - { - data << uint8(1); // no text - } - - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp deleted file mode 100755 index 7d4e4ec28ae..00000000000 --- a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * - * 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 "WorldSession.h" -#include "WorldPacket.h" -#include "DBCStores.h" -#include "Player.h" -#include "Group.h" -#include "LFGMgr.h" -#include "ObjectMgr.h" -#include "GroupMgr.h" -#include "InstanceScript.h" - -void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) -{ - data << uint32(lock.size()); // Size of lock dungeons - for (LfgLockMap::const_iterator it = lock.begin(); it != lock.end(); ++it) - { - data << uint32(it->first); // Dungeon entry (id + type) - data << uint32(it->second); // Lock status - data << uint32(0); // Unknown 4.2.2 - data << uint32(0); // Unknown 4.2.2 - } -} - -void BuildPartyLockDungeonBlock(WorldPacket& data, const LfgLockPartyMap& lockMap) -{ - data << uint8(lockMap.size()); - for (LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it) - { - data << uint64(it->first); // Player guid - BuildPlayerLockDungeonBlock(data, it->second); - } -} - -void WorldSession::HandleLfgJoinOpcode(WorldPacket& recv_data) -{ - if (!sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE) || - (GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID())) - { - recv_data.rfinish(); - return; - } - - uint8 numDungeons; - uint32 dungeon; - uint32 roles; - - recv_data >> roles; - recv_data.read_skip<uint16>(); // uint8 (always 0) - uint8 (always 0) - recv_data >> numDungeons; - if (!numDungeons) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_JOIN [" UI64FMTD "] no dungeons selected", GetPlayer()->GetGUID()); - recv_data.rfinish(); - return; - } - - LfgDungeonSet newDungeons; - for (int8 i = 0 ; i < numDungeons; ++i) - { - recv_data >> dungeon; - newDungeons.insert((dungeon & 0x00FFFFFF)); // remove the type from the dungeon entry - } - - recv_data.read_skip<uint32>(); // for 0..uint8 (always 3) { uint8 (always 0) } - - std::string comment; - recv_data >> comment; - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_JOIN [" UI64FMTD "] roles: %u, Dungeons: %u, Comment: %s", GetPlayer()->GetGUID(), roles, uint8(newDungeons.size()), comment.c_str()); - sLFGMgr->Join(GetPlayer(), uint8(roles), newDungeons, comment); -} - -void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/) -{ - Group* grp = GetPlayer()->GetGroup(); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", GetPlayer()->GetGUID(), grp ? 1 : 0); - - // Check cheating - only leader can leave the queue - if (!grp || grp->GetLeaderGUID() == GetPlayer()->GetGUID()) - sLFGMgr->Leave(GetPlayer(), grp); -} - -void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recv_data) -{ - uint32 lfgGroupID; // Internal lfgGroupID - bool accept; // Accept to join? - recv_data >> lfgGroupID; - recv_data >> accept; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_PROPOSAL_RESULT [" UI64FMTD "] proposal: %u accept: %u", GetPlayer()->GetGUID(), lfgGroupID, accept ? 1 : 0); - sLFGMgr->UpdateProposal(lfgGroupID, GetPlayer()->GetGUID(), accept); -} - -void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recv_data) -{ - uint8 roles; - recv_data >> roles; // Player Group Roles - uint64 guid = GetPlayer()->GetGUID(); - Group* grp = GetPlayer()->GetGroup(); - if (!grp) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_ROLES [" UI64FMTD "] Not in group", guid); - return; - } - uint64 gguid = grp->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_ROLES: Group [" UI64FMTD "], Player [" UI64FMTD "], Roles: %u", gguid, guid, roles); - sLFGMgr->UpdateRoleCheck(gguid, guid, roles); -} - -void WorldSession::HandleLfgSetCommentOpcode(WorldPacket& recv_data) -{ - std::string comment; - recv_data >> comment; - uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_LFG_COMMENT [" UI64FMTD "] comment: %s", guid, comment.c_str()); - - sLFGMgr->SetComment(guid, comment); -} - -void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recv_data) -{ - bool agree; // Agree to kick player - recv_data >> agree; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", GetPlayer()->GetGUID(), agree ? 1 : 0); - sLFGMgr->UpdateBoot(GetPlayer(), agree); -} - -void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data) -{ - bool out; - recv_data >> out; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_TELEPORT [" UI64FMTD "] out: %u", GetPlayer()->GetGUID(), out ? 1 : 0); - sLFGMgr->TeleportPlayer(GetPlayer(), out, true); -} - -void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recv_data*/) -{ - uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); - - // Get Random dungeons that can be done at a certain level and expansion - // FIXME - Should return seasonals (when not disabled) - LfgDungeonSet randomDungeons; - uint8 level = GetPlayer()->getLevel(); - uint8 expansion = GetPlayer()->GetSession()->Expansion(); - for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) - { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); - if (dungeon && dungeon->type == LFG_TYPE_RANDOM && dungeon->expansion <= expansion && - dungeon->minlevel <= level && level <= dungeon->maxlevel) - randomDungeons.insert(dungeon->Entry()); - } - - // Get player locked Dungeons - LfgLockMap lock = sLFGMgr->GetLockedDungeons(guid); - uint32 rsize = uint32(randomDungeons.size()); - uint32 lsize = uint32(lock.size()); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PLAYER_INFO [" UI64FMTD "]", guid); - WorldPacket data(SMSG_LFG_PLAYER_INFO, 1 + rsize * (4 + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4) + 4 + lsize * (1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4)); - - data << uint8(randomDungeons.size()); // Random Dungeon count - for (LfgDungeonSet::const_iterator it = randomDungeons.begin(); it != randomDungeons.end(); ++it) - { - data << uint32(*it); // Dungeon Entry (id + type) - LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(*it, level); - Quest const* qRew = NULL; - uint8 done = 0; - if (reward) - { - qRew = sObjectMgr->GetQuestTemplate(reward->reward[0].questId); - if (qRew) - { - done = !GetPlayer()->CanRewardQuest(qRew, false); - if (done) - qRew = sObjectMgr->GetQuestTemplate(reward->reward[1].questId); - } - } - if (qRew) - { - data << uint8(done); - data << uint32(qRew->GetRewOrReqMoney()); - data << uint32(qRew->XPValue(GetPlayer())); - data << uint32(reward->reward[done].variableMoney); - data << uint32(reward->reward[done].variableXP); - data << uint8(qRew->GetRewItemsCount()); - if (qRew->GetRewItemsCount()) - { - ItemTemplate const* iProto = NULL; - for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (!qRew->RewardItemId[i]) - continue; - - iProto = sObjectMgr->GetItemTemplate(qRew->RewardItemId[i]); - - data << uint32(qRew->RewardItemId[i]); - data << uint32(iProto ? iProto->DisplayInfoID : 0); - data << uint32(qRew->RewardItemIdCount[i]); - } - } - } - else - { - data << uint8(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint8(0); - } - } - BuildPlayerLockDungeonBlock(data, lock); - SendPacket(&data); -} - -void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recv_data*/) -{ - uint64 guid = GetPlayer()->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFD_PARTY_LOCK_INFO_REQUEST [" UI64FMTD "]", guid); - - Group* grp = GetPlayer()->GetGroup(); - if (!grp) - return; - - // Get the locked dungeons of the other party members - LfgLockPartyMap lockMap; - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* plrg = itr->getSource(); - if (!plrg) - continue; - - uint64 pguid = plrg->GetGUID(); - if (pguid == guid) - continue; - - lockMap[pguid] = sLFGMgr->GetLockedDungeons(pguid); - } - - uint32 size = 0; - for (LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it) - size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PARTY_INFO [" UI64FMTD "]", guid); - WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size); - BuildPartyLockDungeonBlock(data, lockMap); - SendPacket(&data); -} - -void WorldSession::HandleLfrSearchOpcode(WorldPacket& recv_data) -{ - uint32 entry; // Raid id to search - recv_data >> entry; - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_JOIN [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), entry); - //SendLfrUpdateListOpcode(entry); -} - -void WorldSession::HandleLfrLeaveOpcode(WorldPacket& recv_data) -{ - uint32 dungeonId; // Raid id queue to leave - recv_data >> dungeonId; - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SEARCH_LFG_LEAVE [" UI64FMTD "] dungeonId: %u", GetPlayer()->GetGUID(), dungeonId); - //sLFGMgr->LeaveLfr(GetPlayer(), dungeonId); -} - -void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData) -{ - bool queued = false; - bool extrainfo = false; - - switch (updateData.updateType) - { - case LFG_UPDATETYPE_JOIN_PROPOSAL: - case LFG_UPDATETYPE_ADDED_TO_QUEUE: - queued = true; - extrainfo = true; - break; - //case LFG_UPDATETYPE_CLEAR_LOCK_LIST: // TODO: Sometimes has extrainfo - Check ocurrences... - case LFG_UPDATETYPE_PROPOSAL_BEGIN: - extrainfo = true; - break; - default: - break; - } - - uint64 guid = GetPlayer()->GetGUID(); - uint8 size = uint8(updateData.dungeons.size()); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PLAYER [" UI64FMTD "] updatetype: %u", guid, updateData.updateType); - WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + size * 4 + updateData.comment.length())); - data << uint8(updateData.updateType); // Lfg Update type - data << uint8(extrainfo); // Extra info - if (extrainfo) - { - data << uint8(queued); // Join the queue - data << uint8(0); // unk - Always 0 - data << uint8(0); // unk - Always 0 - - data << uint8(size); - if (size) - for (LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it) - data << uint32(*it); - data << updateData.comment; - } - SendPacket(&data); -} - -void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData) -{ - bool join = false; - bool extrainfo = false; - bool queued = false; - - switch (updateData.updateType) - { - case LFG_UPDATETYPE_JOIN_PROPOSAL: - extrainfo = true; - break; - case LFG_UPDATETYPE_ADDED_TO_QUEUE: - extrainfo = true; - join = true; - queued = true; - break; - case LFG_UPDATETYPE_CLEAR_LOCK_LIST: - // join = true; // TODO: Sometimes queued and extrainfo - Check ocurrences... - queued = true; - break; - case LFG_UPDATETYPE_PROPOSAL_BEGIN: - extrainfo = true; - join = true; - break; - default: - break; - } - - uint64 guid = GetPlayer()->GetGUID(); - uint8 size = uint8(updateData.dungeons.size()); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PARTY [" UI64FMTD "] updatetype: %u", guid, updateData.updateType); - WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + size * 4 + updateData.comment.length())); - data << uint8(updateData.updateType); // Lfg Update type - data << uint8(extrainfo); // Extra info - if (extrainfo) - { - data << uint8(join); // LFG Join - data << uint8(queued); // Join the queue - data << uint8(0); // unk - Always 0 - data << uint8(0); // unk - Always 0 - for (uint8 i = 0; i < 3; ++i) - data << uint8(0); // unk - Always 0 - - data << uint8(size); - if (size) - for (LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it) - data << uint32(*it); - data << updateData.comment; - } - SendPacket(&data); -} - -void WorldSession::SendLfgRoleChosen(uint64 guid, uint8 roles) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_ROLE_CHOSEN [" UI64FMTD "] guid: [" UI64FMTD "] roles: %u", GetPlayer()->GetGUID(), guid, roles); - - WorldPacket data(SMSG_LFG_ROLE_CHOSEN, 8 + 1 + 4); - data << uint64(guid); // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - SendPacket(&data); -} - -void WorldSession::SendLfgRoleCheckUpdate(const LfgRoleCheck* pRoleCheck) -{ - ASSERT(pRoleCheck); - LfgDungeonSet dungeons; - if (pRoleCheck->rDungeonId) - dungeons.insert(pRoleCheck->rDungeonId); - else - dungeons = pRoleCheck->dungeons; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_ROLE_CHECK_UPDATE [" UI64FMTD "]", GetPlayer()->GetGUID()); - WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1)); - - data << uint32(pRoleCheck->state); // Check result - data << uint8(pRoleCheck->state == LFG_ROLECHECK_INITIALITING); - data << uint8(dungeons.size()); // Number of dungeons - if (!dungeons.empty()) - { - for (LfgDungeonSet::iterator it = dungeons.begin(); it != dungeons.end(); ++it) - { - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(*it); - data << uint32(dungeon ? dungeon->Entry() : 0); // Dungeon - } - } - - data << uint8(pRoleCheck->roles.size()); // Players in group - if (!pRoleCheck->roles.empty()) - { - // Leader info MUST be sent 1st :S - uint64 guid = pRoleCheck->leader; - uint8 roles = pRoleCheck->roles.find(guid)->second; - data << uint64(guid); // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - Player* player = ObjectAccessor::FindPlayer(guid); - data << uint8(player ? player->getLevel() : 0); // Level - - for (LfgRolesMap::const_iterator it = pRoleCheck->roles.begin(); it != pRoleCheck->roles.end(); ++it) - { - if (it->first == pRoleCheck->leader) - continue; - - guid = it->first; - roles = it->second; - data << uint64(guid); // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - player = ObjectAccessor::FindPlayer(guid); - data << uint8(player ? player->getLevel() : 0); // Level - } - } - SendPacket(&data); -} - -void WorldSession::SendLfgJoinResult(const LfgJoinResultData& joinData) -{ - uint32 size = 0; - for (LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it) - size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_JOIN_RESULT [" UI64FMTD "] checkResult: %u checkValue: %u", GetPlayer()->GetGUID(), joinData.result, joinData.state); - WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size); - data << uint32(joinData.result); // Check Result - data << uint32(joinData.state); // Check Value - if (!joinData.lockmap.empty()) - BuildPartyLockDungeonBlock(data, joinData.lockmap); - SendPacket(&data); -} - -void WorldSession::SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_QUEUE_STATUS [" UI64FMTD "] dungeon: %u - waitTime: %d - avgWaitTime: %d - waitTimeTanks: %d - waitTimeHealer: %d - waitTimeDps: %d - queuedTime: %u - tanks: %u - healers: %u - dps: %u", GetPlayer()->GetGUID(), dungeon, waitTime, avgWaitTime, waitTimeTanks, waitTimeHealer, waitTimeDps, queuedTime, tanks, healers, dps); - - WorldPacket data(SMSG_LFG_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 +4 + 1 + 1 + 1 + 4); - data << uint32(dungeon); // Dungeon - data << int32(avgWaitTime); // Average Wait time - data << int32(waitTime); // Wait Time - data << int32(waitTimeTanks); // Wait Tanks - data << int32(waitTimeHealer); // Wait Healers - data << int32(waitTimeDps); // Wait Dps - data << uint8(tanks); // Tanks needed - data << uint8(healers); // Healers needed - data << uint8(dps); // Dps needed - data << uint32(queuedTime); // Player wait time in queue - SendPacket(&data); -} - -void WorldSession::SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward* reward, const Quest* qRew) -{ - if (!rdungeonEntry || !sdungeonEntry || !qRew) - return; - - uint8 itemNum = uint8(qRew ? qRew->GetRewItemsCount() : 0); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PLAYER_REWARD [" UI64FMTD "] rdungeonEntry: %u - sdungeonEntry: %u - done: %u", GetPlayer()->GetGUID(), rdungeonEntry, sdungeonEntry, done); - WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4)); - data << uint32(rdungeonEntry); // Random Dungeon Finished - data << uint32(sdungeonEntry); // Dungeon Finished - data << uint8(done); - data << uint32(1); - data << uint32(qRew->GetRewOrReqMoney()); - data << uint32(qRew->XPValue(GetPlayer())); - data << uint32(reward->reward[done].variableMoney); - data << uint32(reward->reward[done].variableXP); - data << uint8(itemNum); - if (itemNum) - { - ItemTemplate const* iProto = NULL; - for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (!qRew->RewardItemId[i]) - continue; - - iProto = sObjectMgr->GetItemTemplate(qRew->RewardItemId[i]); - - data << uint32(qRew->RewardItemId[i]); - data << uint32(iProto ? iProto->DisplayInfoID : 0); - data << uint32(qRew->RewardItemIdCount[i]); - } - } - SendPacket(&data); -} - -void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot) -{ - uint64 guid = GetPlayer()->GetGUID(); - LfgAnswer playerVote = pBoot->votes.find(guid)->second; - uint8 votesNum = 0; - uint8 agreeNum = 0; - uint32 secsleft = uint8((pBoot->cancelTime - time(NULL)) / 1000); - for (LfgAnswerMap::const_iterator it = pBoot->votes.begin(); it != pBoot->votes.end(); ++it) - { - if (it->second != LFG_ANSWER_PENDING) - { - ++votesNum; - if (it->second == LFG_ANSWER_AGREE) - ++agreeNum; - } - } - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PLAYER [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s", - guid, uint8(pBoot->inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), pBoot->victim, votesNum, agreeNum, secsleft, pBoot->votedNeeded, pBoot->reason.c_str()); - WorldPacket data(SMSG_LFG_BOOT_PLAYER, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length()); - data << uint8(pBoot->inProgress); // Vote in progress - data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote - data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree - data << uint8(0); // Unknown 4.2.2 - data << uint64(pBoot->victim); // Victim GUID - data << uint32(votesNum); // Total Votes - data << uint32(agreeNum); // Agree Count - data << uint32(secsleft); // Time Left - data << uint32(pBoot->votedNeeded); // Needed Votes - data << pBoot->reason.c_str(); // Kick reason - SendPacket(&data); -} - -void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* pProp) -{ - if (!pProp) - return; - - uint64 guid = GetPlayer()->GetGUID(); - LfgProposalPlayerMap::const_iterator itPlayer = pProp->players.find(guid); - if (itPlayer == pProp->players.end()) // Player MUST be in the proposal - return; - - LfgProposalPlayer* ppPlayer = itPlayer->second; - uint32 pLowGroupGuid = ppPlayer->groupLowGuid; - uint32 dLowGuid = pProp->groupLowGuid; - uint32 dungeonId = pProp->dungeonId; - bool isSameDungeon = false; - bool isContinue = false; - Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; - uint32 completedEncounters = 0; - if (grp) - { - uint64 gguid = grp->GetGUID(); - isContinue = grp->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; - isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue; - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), pProp->state); - WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + pProp->players.size() * (4 + 1 + 1 + 1 + 1 +1)); - - if (!isContinue) // Only show proposal dungeon if it's continue - { - LfgDungeonSet playerDungeons = sLFGMgr->GetSelectedDungeons(guid); - if (playerDungeons.size() == 1) - dungeonId = (*playerDungeons.begin()); - } - - if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId)) - { - dungeonId = dungeon->Entry(); - - // Select a player inside to be get completed encounters from - if (grp) - { - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* groupMember = itr->getSource(); - if (groupMember && groupMember->GetMapId() == uint32(dungeon->map)) - { - if (InstanceScript* instance = groupMember->GetInstanceScript()) - completedEncounters = instance->GetCompletedEncounterMask(); - break; - } - } - } - } - - data << uint32(dungeonId); // Dungeon - data << uint8(pProp->state); // Result state - data << uint32(proposalId); // Internal Proposal ID - data << uint32(completedEncounters); // Bosses killed - data << uint8(isSameDungeon); // Silent (show client window) - data << uint8(pProp->players.size()); // Group size - - for (itPlayer = pProp->players.begin(); itPlayer != pProp->players.end(); ++itPlayer) - { - ppPlayer = itPlayer->second; - data << uint32(ppPlayer->role); // Role - data << uint8(itPlayer->first == guid); // Self player - if (!ppPlayer->groupLowGuid) // Player not it a group - { - data << uint8(0); // Not in dungeon - data << uint8(0); // Not same group - } - else - { - data << uint8(ppPlayer->groupLowGuid == dLowGuid); // In dungeon (silent) - data << uint8(ppPlayer->groupLowGuid == pLowGroupGuid); // Same Group than player - } - data << uint8(ppPlayer->accept != LFG_ANSWER_PENDING); // Answered - data << uint8(ppPlayer->accept == LFG_ANSWER_AGREE); // Accepted - } - SendPacket(&data); -} - -void WorldSession::SendLfgUpdateSearch(bool update) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_SEARCH [" UI64FMTD "] update: %u", GetPlayer()->GetGUID(), update ? 1 : 0); - WorldPacket data(SMSG_LFG_UPDATE_SEARCH, 1); - data << uint8(update); // In Lfg Queue? - SendPacket(&data); -} - -void WorldSession::SendLfgDisabled() -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_DISABLED [" UI64FMTD "]", GetPlayer()->GetGUID()); - WorldPacket data(SMSG_LFG_DISABLED, 0); - SendPacket(&data); -} - -void WorldSession::SendLfgOfferContinue(uint32 dungeonEntry) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_OFFER_CONTINUE [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry); - WorldPacket data(SMSG_LFG_OFFER_CONTINUE, 4); - data << uint32(dungeonEntry); - SendPacket(&data); -} - -void WorldSession::SendLfgTeleportError(uint8 err) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_TELEPORT_DENIED [" UI64FMTD "] reason: %u", GetPlayer()->GetGUID(), err); - WorldPacket data(SMSG_LFG_TELEPORT_DENIED, 4); - data << uint32(err); // Error - SendPacket(&data); -} - -/* -void WorldSession::SendLfrUpdateListOpcode(uint32 dungeonEntry) -{ - sLog->outDebug(LOG_FILTER_PACKETIO, "SMSG_LFG_UPDATE_LIST [" UI64FMTD "] dungeon entry: %u", GetPlayer()->GetGUID(), dungeonEntry); - WorldPacket data(SMSG_LFG_UPDATE_LIST); - SendPacket(&data); -} -*/ diff --git a/src/server/game/Server/Protocol/Handlers/LootHandler.cpp b/src/server/game/Server/Protocol/Handlers/LootHandler.cpp deleted file mode 100755 index b17817e196f..00000000000 --- a/src/server/game/Server/Protocol/Handlers/LootHandler.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "Log.h" -#include "Corpse.h" -#include "GameObject.h" -#include "Player.h" -#include "ObjectAccessor.h" -#include "WorldSession.h" -#include "LootMgr.h" -#include "Object.h" -#include "Group.h" -#include "World.h" -#include "Util.h" - -void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); - Player* player = GetPlayer(); - uint64 lguid = player->GetLootGUID(); - Loot* loot = NULL; - uint8 lootSlot = 0; - - recv_data >> lootSlot; - - if (IS_GAMEOBJECT_GUID(lguid)) - { - GameObject* go = player->GetMap()->GetGameObject(lguid); - - // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO - if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) - { - player->SendLootRelease(lguid); - return; - } - - loot = &go->loot; - } - else if (IS_ITEM_GUID(lguid)) - { - Item* pItem = player->GetItemByGuid(lguid); - - if (!pItem) - { - player->SendLootRelease(lguid); - return; - } - - loot = &pItem->loot; - } - else if (IS_CORPSE_GUID(lguid)) - { - Corpse* bones = ObjectAccessor::GetCorpse(*player, lguid); - if (!bones) - { - player->SendLootRelease(lguid); - return; - } - - loot = &bones->loot; - } - else - { - Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); - - bool ok_loot = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); - - if (!ok_loot || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) - { - player->SendLootRelease(lguid); - return; - } - - loot = &creature->loot; - } - - player->StoreLootItem(lootSlot, loot); -} - -void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_MONEY"); - - Player* player = GetPlayer(); - uint64 guid = player->GetLootGUID(); - if (!guid) - return; - - Loot* loot = NULL; - bool shareMoney = true; - - switch (GUID_HIPART(guid)) - { - case HIGHGUID_GAMEOBJECT: - { - GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); - - // do not check distance for GO if player is the owner of it (ex. fishing bobber) - if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player, INTERACTION_DISTANCE)))) - loot = &go->loot; - - break; - } - case HIGHGUID_CORPSE: // remove insignia ONLY in BG - { - Corpse* bones = ObjectAccessor::GetCorpse(*player, guid); - - if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE)) - { - loot = &bones->loot; - shareMoney = false; - } - - break; - } - case HIGHGUID_ITEM: - { - if (Item* item = player->GetItemByGuid(guid)) - { - loot = &item->loot; - shareMoney = false; - } - break; - } - case HIGHGUID_UNIT: - case HIGHGUID_VEHICLE: - { - Creature* creature = player->GetMap()->GetCreature(guid); - bool lootAllowed = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); - if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE)) - { - loot = &creature->loot; - if (creature->isAlive()) - shareMoney = false; - } - break; - } - default: - return; // unlootable type - } - - if (loot) - { - loot->NotifyMoneyRemoved(); - if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player - { - Group* group = player->GetGroup(); - - std::vector<Player*> playersNear; - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* member = itr->getSource(); - if (!member) - continue; - - if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false)) - playersNear.push_back(member); - } - - uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size())); - - for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) - { - (*i)->ModifyMoney(goldPerPlayer); - (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); - - WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); - data << uint32(goldPerPlayer); - data << uint8(playersNear.size() > 1 ? 0 : 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." - (*i)->GetSession()->SendPacket(&data); - } - } - else - { - player->ModifyMoney(loot->gold); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); - - WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); - data << uint32(loot->gold); - data << uint8(1); // "You loot..." - SendPacket(&data); - } - - loot->gold = 0; - } -} - -void WorldSession::HandleLootOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT"); - - uint64 guid; - recv_data >> guid; - - // Check possible cheat - if (!_player->isAlive()) - return; - - GetPlayer()->SendLoot(guid, LOOT_CORPSE); - - // interrupt cast - if (GetPlayer()->IsNonMeleeSpellCasted(false)) - GetPlayer()->InterruptNonMeleeSpells(false); -} - -void WorldSession::HandleLootReleaseOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_RELEASE"); - - // cheaters can modify lguid to prevent correct apply loot release code and re-loot - // use internal stored guid - recv_data.read_skip<uint64>(); // guid; - - if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); -} - -void WorldSession::DoLootRelease(uint64 lguid) -{ - Player *player = GetPlayer(); - Loot *loot; - - player->SetLootGUID(0); - player->SendLootRelease(lguid); - - player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); - - if (!player->IsInWorld()) - return; - - if (IS_GAMEOBJECT_GUID(lguid)) - { - GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); - - // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO - if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) - return; - - loot = &go->loot; - - if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) - { - // locked doors are opened with spelleffect openlock, prevent remove its as looted - go->UseDoorOrButton(); - } - else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) - { - // GO is mineral vein? so it is not removed after its looted - if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) - { - uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; - uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; - - // only vein pass this check - if (go_min != 0 && go_max > go_min) - { - float amount_rate = sWorld->getRate(RATE_MINING_AMOUNT); - float min_amount = go_min*amount_rate; - float max_amount = go_max*amount_rate; - - go->AddUse(); - float uses = float(go->GetUseCount()); - - if (uses < max_amount) - { - if (uses >= min_amount) - { - float chance_rate = sWorld->getRate(RATE_MINING_NEXT); - - int32 ReqValue = 175; - LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); - if (lockInfo) - ReqValue = lockInfo->Skill[0]; - float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); - double chance = pow(0.8*chance_rate, 4*(1/double(max_amount))*double(uses)); - if (roll_chance_f((float)(100*chance+skill))) - { - go->SetLootState(GO_READY); - } - else // not have more uses - go->SetLootState(GO_JUST_DEACTIVATED); - } - else // 100% chance until min uses - go->SetLootState(GO_READY); - } - else // max uses already - go->SetLootState(GO_JUST_DEACTIVATED); - } - else // not vein - go->SetLootState(GO_JUST_DEACTIVATED); - } - else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) - { // The fishing hole used once more - go->AddUse(); // if the max usage is reached, will be despawned in next tick - if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) - { - go->SetLootState(GO_JUST_DEACTIVATED); - } - else - go->SetLootState(GO_READY); - } - else // not chest (or vein/herb/etc) - go->SetLootState(GO_JUST_DEACTIVATED); - - loot->clear(); - } - else - { - // not fully looted object - go->SetLootState(GO_ACTIVATED); - - // if the round robin player release, reset it. - if (player->GetGUID() == loot->roundRobinPlayer) - { - if (Group* group = player->GetGroup()) - { - if (group->GetLootMethod() != MASTER_LOOT) - { - loot->roundRobinPlayer = 0; - } - } - else - loot->roundRobinPlayer = 0; - } - } - } - else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG - { - Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid); - if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) - return; - - loot = &corpse->loot; - - if (loot->isLooted()) - { - loot->clear(); - corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); - } - } - else if (IS_ITEM_GUID(lguid)) - { - Item* pItem = player->GetItemByGuid(lguid); - if (!pItem) - return; - - ItemTemplate const* proto = pItem->GetTemplate(); - - // destroy only 5 items from stack in case prospecting and milling - if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) - { - pItem->m_lootGenerated = false; - pItem->loot.clear(); - - uint32 count = pItem->GetCount(); - - // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. - if (count > 5) - count = 5; - - player->DestroyItemCount(pItem, count, true); - } - else - // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. - player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); - return; // item can be looted only single player - } - else - { - Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); - - bool ok_loot = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); - if (!ok_loot || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) - return; - - loot = &creature->loot; - if (loot->isLooted()) - { - // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact - if (!creature->isAlive()) - creature->AllLootRemovedFromCorpse(); - - creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - loot->clear(); - } - else - { - // if the round robin player release, reset it. - if (player->GetGUID() == loot->roundRobinPlayer) - { - if (Group* group = player->GetGroup()) - { - if (group->GetLootMethod() != MASTER_LOOT) - { - loot->roundRobinPlayer = 0; - group->SendLooter(creature, NULL); - - // force update of dynamic flags, otherwise other group's players still not able to loot. - creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); - } - } - else - loot->roundRobinPlayer = 0; - } - } - } - - //Player is not looking at loot list, he doesn't need to see updates on the loot list - loot->RemoveLooter(player->GetGUID()); -} - -void WorldSession::HandleLootMasterGiveOpcode(WorldPacket & recv_data) -{ - uint8 slotid; - uint64 lootguid, target_playerguid; - - recv_data >> lootguid >> slotid >> target_playerguid; - - if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID()) - { - _player->SendLootRelease(GetPlayer()->GetLootGUID()); - return; - } - - Player* target = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(target_playerguid, 0, HIGHGUID_PLAYER)); - if (!target) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName()); - - if (_player->GetLootGUID() != lootguid) - return; - - Loot* pLoot = NULL; - - if (IS_CRE_OR_VEH_GUID(GetPlayer()->GetLootGUID())) - { - Creature* creature = GetPlayer()->GetMap()->GetCreature(lootguid); - if (!creature) - return; - - pLoot = &creature->loot; - } - else if (IS_GAMEOBJECT_GUID(GetPlayer()->GetLootGUID())) - { - GameObject* pGO = GetPlayer()->GetMap()->GetGameObject(lootguid); - if (!pGO) - return; - - pLoot = &pGO->loot; - } - - if (!pLoot) - return; - - if (slotid > pLoot->items.size()) - { - sLog->outDebug(LOG_FILTER_LOOT, "MasterLootItem: Player %s might be using a hack! (slot %d, size %lu)", GetPlayer()->GetName(), slotid, (unsigned long)pLoot->items.size()); - return; - } - - LootItem& item = pLoot->items[slotid]; - - ItemPosCountVec dest; - InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count); - if (msg != EQUIP_ERR_OK) - { - target->SendEquipError(msg, NULL, NULL, item.itemid); - // send duplicate of error massage to master looter - _player->SendEquipError(msg, NULL, NULL, item.itemid); - return; - } - - // list of players allowed to receive this item in trade - AllowedLooterSet looters = item.GetAllowedLooters(); - - // not move item from loot to target inventory - Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId, looters); - target->SendNewItem(newitem, uint32(item.count), false, false, true); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, pLoot->loot_type, item.count); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count); - - // mark as looted - item.count=0; - item.is_looted=true; - - pLoot->NotifyItemRemoved(slotid); - --pLoot->unlootedCount; -} - diff --git a/src/server/game/Server/Protocol/Handlers/MailHandler.cpp b/src/server/game/Server/Protocol/Handlers/MailHandler.cpp deleted file mode 100755 index 95459bae0fa..00000000000 --- a/src/server/game/Server/Protocol/Handlers/MailHandler.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * - * 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 "DatabaseEnv.h" -#include "Mail.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "Language.h" -#include "DBCStores.h" -#include "Item.h" -#include "AccountMgr.h" - -void WorldSession::HandleSendMail(WorldPacket & recv_data) -{ - uint64 mailbox, unk3; - std::string receiver, subject, body; - uint32 unk1, unk2, money, COD; - uint8 unk4; - recv_data >> mailbox; - recv_data >> receiver; - - recv_data >> subject; - - recv_data >> body; - - recv_data >> unk1; // stationery? - recv_data >> unk2; // 0x00000000 - - uint8 items_count; - recv_data >> items_count; // attached items count - - if (items_count > MAX_MAIL_ITEMS) // client limit - { - GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); - recv_data.rfinish(); // set to end to avoid warnings spam - return; - } - - uint64 itemGUIDs[MAX_MAIL_ITEMS]; - - for (uint8 i = 0; i < items_count; ++i) - { - recv_data.read_skip<uint8>(); // item slot in mail, not used - recv_data >> itemGUIDs[i]; - } - - recv_data >> money >> COD; // money and cod - recv_data >> unk3; // const 0 - recv_data >> unk4; // const 0 - - // packet read complete, now do check - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - if (receiver.empty()) - return; - - Player* player = _player; - - if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); - return; - } - - uint64 rc = 0; - if (normalizePlayerName(receiver)) - rc = sObjectMgr->GetPlayerGUIDByName(receiver); - - if (!rc) - { - sLog->outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", - player->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); - return; - } - - sLog->outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); - - if (player->GetGUID() == rc) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); - return; - } - - uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client - - uint32 reqmoney = cost + money; - - if (!player->HasEnoughMoney(reqmoney)) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); - return; - } - - Player* receive = ObjectAccessor::FindPlayer(rc); - - uint32 rc_team = 0; - uint8 mails_count = 0; //do not allow to send to one player more than 100 mails - uint8 receiveLevel = 0; - - if (receive) - { - rc_team = receive->GetTeam(); - mails_count = receive->GetMailSize(); - receiveLevel = receive->getLevel(); - } - else - { - rc_team = sObjectMgr->GetPlayerTeamByGUID(rc); - if (QueryResult result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", GUID_LOPART(rc))) - { - Field* fields = result->Fetch(); - mails_count = fields[0].GetUInt32(); - } - if (QueryResult result = CharacterDatabase.PQuery("SELECT level FROM characters WHERE guid = '%u'", GUID_LOPART(rc))) - { - Field* fields = result->Fetch(); - receiveLevel = fields[0].GetUInt8(); - } - } - //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. - if (mails_count > 100) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); - return; - } - // test the receiver's Faction... or all items are account bound - bool accountBound = items_count ? true : false; - for (uint8 i = 0; i < items_count; ++i) - { - Item* item = player->GetItemByGuid(itemGUIDs[i]); - if (item) - { - ItemTemplate const* itemProto = item->GetTemplate(); - if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) - { - accountBound = false; - break; - } - } - } - - if (!accountBound && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeam() != rc_team && AccountMgr::IsPlayerAccount(GetSecurity())) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); - return; - } - - if (receiveLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); - return; - } - - uint32 rc_account = receive - ? receive->GetSession()->GetAccountId() - : sObjectMgr->GetPlayerAccountIdByGUID(rc); - - Item* items[MAX_MAIL_ITEMS]; - - for (uint8 i = 0; i < items_count; ++i) - { - if (!itemGUIDs[i]) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); - return; - } - - Item* item = player->GetItemByGuid(itemGUIDs[i]); - - // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) - if (!item) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); - return; - } - - if (!item->CanBeTraded(true)) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); - return; - } - - if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != rc_account) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); - return; - } - - if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); - return; - } - - if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); - return; - } - - if (item->IsNotEmptyBag()) - { - player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS); - return; - } - - items[i] = item; - } - - player->SendMailResult(0, MAIL_SEND, MAIL_OK); - - player->ModifyMoney(-int32(reqmoney)); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); - - bool needItemDelay = false; - - MailDraft draft(subject, body); - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - - if (items_count > 0 || money > 0) - { - if (items_count > 0) - { - for (uint8 i = 0; i < items_count; ++i) - { - Item* item = items[i]; - if (!AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", - GetPlayerName(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account); - } - - item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable - player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); - - item->DeleteFromInventoryDB(trans); // deletes item from character's inventory - item->SetOwnerGUID(rc); - item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone - - draft.AddItem(item); - } - - // if item send to character at another account, then apply item delivery delay - needItemDelay = player->GetSession()->GetAccountId() != rc_account; - } - - if (money > 0 && !AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", - GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account); - } - } - - // If theres is an item, there is a one hour delivery delay if sent to another account's character. - uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; - - // will delete item or place to receiver mail list - draft - .AddMoney(money) - .AddCOD(COD) - .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); - - player->SaveInventoryAndGoldToDB(trans); - CharacterDatabase.CommitTransaction(trans); -} - -//called when mail is read -void WorldSession::HandleMailMarkAsRead(WorldPacket & recv_data) -{ - uint64 mailbox; - uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Player* player = _player; - Mail* m = player->GetMail(mailId); - if (m) - { - if (player->unReadMails) - --player->unReadMails; - m->checked = m->checked | MAIL_CHECK_MASK_READ; - player->m_mailsUpdated = true; - m->state = MAIL_STATE_CHANGED; - } -} - -//called when client deletes mail -void WorldSession::HandleMailDelete(WorldPacket & recv_data) -{ - uint64 mailbox; - uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; - recv_data.read_skip<uint32>(); // mailTemplateId - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Mail* m = _player->GetMail(mailId); - Player* player = _player; - player->m_mailsUpdated = true; - if (m) - { - // delete shouldn't show up for COD mails - if (m->COD) - { - player->SendMailResult(mailId, MAIL_DELETED, MAIL_ERR_INTERNAL_ERROR); - return; - } - - m->state = MAIL_STATE_DELETED; - } - player->SendMailResult(mailId, MAIL_DELETED, MAIL_OK); -} - -void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data) -{ - uint64 mailbox; - uint32 mailId; - recv_data >> mailbox; - recv_data >> mailId; - recv_data.read_skip<uint64>(); // original sender GUID for return to, not used - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Player* player = _player; - Mail* m = player->GetMail(mailId); - if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) - { - player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR); - return; - } - //we can return mail now - //so firstly delete the old one - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("DELETE FROM mail WHERE id = '%u'", mailId); // needed? - trans->PAppend("DELETE FROM mail_items WHERE mail_id = '%u'", mailId); - player->RemoveMail(mailId); - - // only return mail if the player exists (and delete if not existing) - if (m->messageType == MAIL_NORMAL && m->sender) - { - MailDraft draft(m->subject, m->body); - if (m->mailTemplateId) - draft = MailDraft(m->mailTemplateId, false); // items already included - - if (m->HasItems()) - { - for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) - { - Item* item = player->GetMItem(itr2->item_guid); - if (item) - draft.AddItem(item); - else - { - //WTF? - } - - player->RemoveMItem(itr2->item_guid); - } - } - draft.AddMoney(m->money).SendReturnToSender(GetAccountId(), m->receiver, m->sender, trans); - } - - CharacterDatabase.CommitTransaction(trans); - - delete m; //we can deallocate old mail - player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_OK); -} - -//called when player takes item attached in mail -void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) -{ - uint64 mailbox; - uint32 mailId; - uint32 itemId; - recv_data >> mailbox; - recv_data >> mailId; - recv_data >> itemId; // item guid low - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Player* player = _player; - - Mail* m = player->GetMail(mailId); - if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) - { - player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR); - return; - } - - // prevent cheating with skip client money check - if (!player->HasEnoughMoney(m->COD)) - { - player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY); - return; - } - - Item* it = player->GetMItem(itemId); - - ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, it, false); - if (msg == EQUIP_ERR_OK) - { - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - m->RemoveItem(itemId); - m->removedItems.push_back(itemId); - - if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail - { - uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER); - Player* receive = ObjectAccessor::FindPlayer(sender_guid); - - uint32 sender_accId = 0; - - if (!AccountMgr::IsPlayerAccount(GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - std::string sender_name; - if (receive) - { - sender_accId = receive->GetSession()->GetAccountId(); - sender_name = receive->GetName(); - } - else - { - // can be calculated early - sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid); - - if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name)) - sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); - } - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", - GetPlayerName(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); - } - else if (!receive) - sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid); - - // check player existence - if (receive || sender_accId) - { - MailDraft(m->subject, "") - .AddMoney(m->COD) - .SendMailTo(trans, MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); - } - - player->ModifyMoney(-int32(m->COD)); - } - m->COD = 0; - m->state = MAIL_STATE_CHANGED; - player->m_mailsUpdated = true; - player->RemoveMItem(it->GetGUIDLow()); - - uint32 count = it->GetCount(); // save counts before store and possible merge with deleting - player->MoveItemToInventory(dest, it, true); - - player->SaveInventoryAndGoldToDB(trans); - player->_SaveMail(trans); - CharacterDatabase.CommitTransaction(trans); - - player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); - } - else - player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); -} - -void WorldSession::HandleMailTakeMoney(WorldPacket& recv_data) -{ - uint64 mailbox; - uint64 money; - uint32 mailId; - - recv_data >> mailbox; - recv_data >> mailId; - recv_data >> money; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Player* player = _player; - - Mail* m = player->GetMail(mailId); - if ((!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) || - (money > 0 && m->money != money)) - { - player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_ERR_INTERNAL_ERROR); - return; - } - - player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_OK); - - player->ModifyMoney(money); - m->money = 0; - m->state = MAIL_STATE_CHANGED; - player->m_mailsUpdated = true; - - // save money and mail to prevent cheating - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - player->SaveGoldToDB(trans); - player->_SaveMail(trans); - CharacterDatabase.CommitTransaction(trans); -} - -//called when player lists his received mails -void WorldSession::HandleGetMailList(WorldPacket & recv_data) -{ - uint64 mailbox; - recv_data >> mailbox; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Player* player = _player; - - //load players mails, and mailed items - if (!player->m_mailsLoaded) - player ->_LoadMail(); - - // client can't work with packets > max int16 value - const uint32 maxPacketSize = 32767; - - uint32 mailsCount = 0; // real send to client mails amount - uint32 realCount = 0; // real mails amount - - WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size - data << uint32(0); // real mail's count - data << uint8(0); // mail's count - time_t cur_time = time(NULL); - - for (PlayerMails::iterator itr = player->GetMailBegin(); itr != player->GetMailEnd(); ++itr) - { - // packet send mail count as uint8, prevent overflow - if (mailsCount >= 254) - { - realCount += 1; - continue; - } - - // skip deleted or not delivered (deliver delay not expired) mails - if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) - continue; - - uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) - - size_t next_mail_size = 2+4+1+((*itr)->messageType == MAIL_NORMAL ? 8 : 4)+4*8+((*itr)->subject.size()+1)+((*itr)->body.size()+1)+1+item_count*(1+4+4+7*3*4+4+4+4+4+4+4+1); - - if (data.wpos()+next_mail_size > maxPacketSize) - { - realCount += 1; - continue; - } - - data << uint16(next_mail_size); // Message size - data << uint32((*itr)->messageID); // Message ID - data << uint8((*itr)->messageType); // Message Type - - switch ((*itr)->messageType) - { - case MAIL_NORMAL: // sender guid - data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER)); - break; - case MAIL_CREATURE: - case MAIL_GAMEOBJECT: - case MAIL_AUCTION: - data << uint32((*itr)->sender); // creature/gameobject entry, auction id - break; - case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI - data << uint32(0); // item entry - break; - } - - data << uint64((*itr)->COD); // COD - data << uint32(0); // probably changed in 3.3.3 - data << uint32((*itr)->stationery); // stationery (Stationery.dbc) - data << uint64((*itr)->money); // Gold - data << uint32((*itr)->checked); // flags - data << float(((*itr)->expire_time-time(NULL))/DAY); // Time - data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc) - data << (*itr)->subject; // Subject string - once 00, when mail type = 3, max 256 - data << (*itr)->body; // message? max 8000 - data << uint8(item_count); // client limit is 0x10 - - for (uint8 i = 0; i < item_count; ++i) - { - Item* item = player->GetMItem((*itr)->items[i].item_guid); - // item index (0-6?) - data << uint8(i); - // item guid low? - data << uint32((item ? item->GetGUIDLow() : 0)); - // entry - data << uint32((item ? item->GetEntry() : 0)); - for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) - { - data << uint32((item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0)); - data << uint32((item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0)); - data << uint32((item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0)); - } - // can be negative - data << int32((item ? item->GetItemRandomPropertyId() : 0)); - // unk - data << uint32((item ? item->GetItemSuffixFactor() : 0)); - // stack count - data << uint32((item ? item->GetCount() : 0)); - // charges - data << uint32((item ? item->GetSpellCharges() : 0)); - // durability - data << uint32((item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0)); - // durability - data << uint32((item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0)); - // unknown wotlk - data << uint8(0); - } - - realCount += 1; - mailsCount += 1; - } - - data.put<uint32>(0, realCount); // this will display warning about undelivered mail to player if realCount > mailsCount - data.put<uint8>(4, mailsCount); // set real send mails to client - SendPacket(&data); - - // recalculate m_nextMailDelivereTime and unReadMails - _player->UpdateNextMailTimeAndUnreads(); -} - -//used when player copies mail body to his inventory -void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data) -{ - uint64 mailbox; - uint32 mailId; - - recv_data >> mailbox; - recv_data >> mailId; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) - return; - - Player* player = _player; - - Mail* m = player->GetMail(mailId); - if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) - { - player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); - return; - } - - Item* bodyItem = new Item; // This is not bag and then can be used new Item. - if (!bodyItem->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, player)) - { - delete bodyItem; - return; - } - - // in mail template case we need create new item text - if (m->mailTemplateId) - { - MailTemplateEntry const* mailTemplateEntry = sMailTemplateStore.LookupEntry(m->mailTemplateId); - if (!mailTemplateEntry) - { - player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); - return; - } - - bodyItem->SetText(mailTemplateEntry->content); - } - else - bodyItem->SetText(m->body); - - bodyItem->SetUInt32Value(ITEM_FIELD_CREATOR, m->sender); - bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_MAIL_TEXT_MASK); - - sLog->outDetail("HandleMailCreateTextItem mailid=%u", mailId); - - ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false); - if (msg == EQUIP_ERR_OK) - { - m->checked = m->checked | MAIL_CHECK_MASK_COPIED; - m->state = MAIL_STATE_CHANGED; - player->m_mailsUpdated = true; - - player->StoreItem(dest, bodyItem, true); - player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_OK); - } - else - { - player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_EQUIP_ERROR, msg); - delete bodyItem; - } -} - -//TODO Fix me! ... this void has probably bad condition, but good data are sent -void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recv_data*/) -{ - WorldPacket data(MSG_QUERY_NEXT_MAIL_TIME, 8); - - if (!_player->m_mailsLoaded) - _player->_LoadMail(); - - if (_player->unReadMails > 0) - { - data << uint32(0); // float - data << uint32(0); // count - - uint32 count = 0; - time_t now = time(NULL); - for (PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr) - { - Mail* m = (*itr); - // must be not checked yet - if (m->checked & MAIL_CHECK_MASK_READ) - continue; - - // and already delivered - if (now < m->deliver_time) - continue; - - if (m->messageType) - data << uint64(m->sender); // player guid - else - data << uint32(m->sender); // creature entry - - switch (m->messageType) - { - case MAIL_AUCTION: - data << uint32(2); - data << uint32(2); - data << uint32(m->stationery); - break; - default: - data << uint32(0); - data << uint32(0); - data << uint32(m->stationery); - break; - } - data << uint32(0xC6000000); // float unk, time or something - - ++count; - if (count == 2) // do not display more than 2 mails - break; - } - data.put<uint32>(4, count); - } - else - { - data << uint32(0xC7A8C000); - data << uint32(0x00000000); - } - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp deleted file mode 100755 index 843aa8fd6c0..00000000000 --- a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp +++ /dev/null @@ -1,1744 +0,0 @@ -/* - * 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 "Language.h" -#include "DatabaseEnv.h" -#include "WorldPacket.h" -#include "Opcodes.h" -#include "Log.h" -#include "Player.h" -#include "GossipDef.h" -#include "World.h" -#include "ObjectMgr.h" -#include "GuildMgr.h" -#include "WorldSession.h" -#include "BigNumber.h" -#include "SHA1.h" -#include "UpdateData.h" -#include "LootMgr.h" -#include "Chat.h" -#include "zlib.h" -#include "ObjectAccessor.h" -#include "Object.h" -#include "Battleground.h" -#include "OutdoorPvP.h" -#include "Pet.h" -#include "SocialMgr.h" -#include "CellImpl.h" -#include "AccountMgr.h" -#include "Vehicle.h" -#include "CreatureAI.h" -#include "DBCEnums.h" -#include "ScriptMgr.h" -#include "MapManager.h" -#include "InstanceScript.h" -#include "GameObjectAI.h" -#include "Group.h" -#include "AccountMgr.h" - -void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_REPOP_REQUEST Message"); - - recv_data.read_skip<uint8>(); - - if (GetPlayer()->isAlive() || GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - return; - - if (GetPlayer()->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) - return; // silently return, client should display the error by itself - - // the world update order is sessions, players, creatures - // the netcode runs in parallel with all of these - // creatures can kill players - // so if the server is lagging enough the player can - // release spirit after he's killed but before he is updated - if (GetPlayer()->getDeathState() == JUST_DIED) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "HandleRepopRequestOpcode: got request after player %s(%d) was killed and before he was updated", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - GetPlayer()->KillPlayer(); - } - - //this is spirit release confirm? - GetPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - GetPlayer()->BuildPlayerRepop(); - GetPlayer()->RepopAtGraveyard(); -} - -void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GOSSIP_SELECT_OPTION"); - - uint32 gossipListId; - uint32 menuId; - uint64 guid; - std::string code = ""; - - recv_data >> guid >> menuId >> gossipListId; - - if (_player->PlayerTalkClass->IsGossipOptionCoded(gossipListId)) - recv_data >> code; - - Creature* unit = NULL; - GameObject* go = NULL; - if (IS_CRE_OR_VEH_GUID(guid)) - { - unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - } - else if (IS_GAMEOBJECT_GUID(guid)) - { - go = _player->GetMap()->GetGameObject(guid); - if (!go) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleGossipSelectOptionOpcode - GameObject (GUID: %u) not found.", uint32(GUID_LOPART(guid))); - return; - } - } - else - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleGossipSelectOptionOpcode - unsupported GUID type for highguid %u. lowpart %u.", uint32(GUID_HIPART(guid)), uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if ((unit && unit->GetCreatureInfo()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); - if (unit) - unit->LastUsedScriptID = unit->GetCreatureInfo()->ScriptID; - if (go) - go->LastUsedScriptID = go->GetGOInfo()->ScriptId; - _player->PlayerTalkClass->SendCloseGossip(); - return; - } - if (!code.empty()) - { - if (unit) - { - unit->AI()->sGossipSelectCode(_player, menuId, gossipListId, code.c_str()); - if (!sScriptMgr->OnGossipSelectCode(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str())) - _player->OnGossipSelect(unit, gossipListId, menuId); - } - else - { - go->AI()->GossipSelectCode(_player, menuId, gossipListId, code.c_str()); - sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str()); - } - } - else - { - if (unit) - { - unit->AI()->sGossipSelect(_player, menuId, gossipListId); - if (!sScriptMgr->OnGossipSelect(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId))) - _player->OnGossipSelect(unit, gossipListId, menuId); - } - else - { - go->AI()->GossipSelect(_player, menuId, gossipListId); - sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId)); - } - } -} - -void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_WHO Message"); - - uint32 matchcount = 0; - - uint32 level_min, level_max, racemask, classmask, zones_count, str_count; - uint32 zoneids[10]; // 10 is client limit - std::string player_name, guild_name; - - recv_data >> level_min; // maximal player level, default 0 - recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) - recv_data >> player_name; // player name, case sensitive... - - recv_data >> guild_name; // guild name, case sensitive... - - recv_data >> racemask; // race mask - recv_data >> classmask; // class mask - recv_data >> zones_count; // zones count, client limit = 10 (2.0.10) - - if (zones_count > 10) - return; // can't be received from real client or broken packet - - for (uint32 i = 0; i < zones_count; ++i) - { - uint32 temp; - recv_data >> temp; // zone id, 0 if zone is unknown... - zoneids[i] = temp; - sLog->outDebug(LOG_FILTER_NETWORKIO, "Zone %u: %u", i, zoneids[i]); - } - - recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) - - if (str_count > 4) - return; // can't be received from real client or broken packet - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); - - std::wstring str[4]; // 4 is client limit - for (uint32 i = 0; i < str_count; ++i) - { - std::string temp; - recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? - - if (!Utf8toWStr(temp, str[i])) - continue; - - wstrToLower(str[i]); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "String %u: %s", i, temp.c_str()); - } - - std::wstring wplayer_name; - std::wstring wguild_name; - if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) - return; - wstrToLower(wplayer_name); - wstrToLower(wguild_name); - - // client send in case not set max level value 100 but Trinity supports 255 max level, - // update it to show GMs with characters after 100 level - if (level_max >= MAX_LEVEL) - level_max = STRONG_MAX_LEVEL; - - uint32 team = _player->GetTeam(); - uint32 security = GetSecurity(); - bool allowTwoSideWhoList = sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); - uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); - uint32 displaycount = 0; - - WorldPacket data(SMSG_WHO, 50); // guess size - data << uint32(matchcount); // placeholder, count of players matching criteria - data << uint32(displaycount); // placeholder, count of players displayed - - TRINITY_READ_GUARD(HashMapHolder<Player>::LockType, *HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType const& m = sObjectAccessor->GetPlayers(); - for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) - { - if (AccountMgr::IsPlayerAccount(security)) - { - // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST - if (itr->second->GetTeam() != team && !allowTwoSideWhoList) - continue; - - // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST - if ((itr->second->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList))) - continue; - } - - //do not process players which are not in world - if (!(itr->second->IsInWorld())) - continue; - - // check if target is globally visible for player - if (!(itr->second->IsVisibleGloballyFor(_player))) - continue; - - // check if target's level is in level range - uint8 lvl = itr->second->getLevel(); - if (lvl < level_min || lvl > level_max) - continue; - - // check if class matches classmask - uint32 class_ = itr->second->getClass(); - if (!(classmask & (1 << class_))) - continue; - - // check if race matches racemask - uint32 race = itr->second->getRace(); - if (!(racemask & (1 << race))) - continue; - - uint32 pzoneid = itr->second->GetZoneId(); - uint8 gender = itr->second->getGender(); - - bool z_show = true; - for (uint32 i = 0; i < zones_count; ++i) - { - if (zoneids[i] == pzoneid) - { - z_show = true; - break; - } - - z_show = false; - } - if (!z_show) - continue; - - std::string pname = itr->second->GetName(); - std::wstring wpname; - if (!Utf8toWStr(pname, wpname)) - continue; - wstrToLower(wpname); - - if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) - continue; - - std::string gname = sGuildMgr->GetGuildNameById(itr->second->GetGuildId()); - std::wstring wgname; - if (!Utf8toWStr(gname, wgname)) - continue; - wstrToLower(wgname); - - if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) - continue; - - std::string aname; - if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId())) - aname = areaEntry->area_name[GetSessionDbcLocale()]; - - bool s_show = true; - for (uint32 i = 0; i < str_count; ++i) - { - if (!str[i].empty()) - { - if (wgname.find(str[i]) != std::wstring::npos || - wpname.find(str[i]) != std::wstring::npos || - Utf8FitTo(aname, str[i])) - { - s_show = true; - break; - } - s_show = false; - } - } - if (!s_show) - continue; - - // 49 is maximum player count sent to client - can be overridden - // through config, but is unstable - if ((matchcount++) >= sWorld->getIntConfig(CONFIG_MAX_WHO)) - continue; - - data << pname; // player name - data << gname; // guild name - data << uint32(lvl); // player level - data << uint32(class_); // player class - data << uint32(race); // player race - data << uint8(gender); // player gender - data << uint32(pzoneid); // player zone id - - ++displaycount; - } - - data.put(0, displaycount); // insert right count, count displayed - data.put(4, matchcount); // insert right count, count of matches - - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Send SMSG_WHO Message"); -} - -void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity()); - - if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); - - uint8 reason = 0; - - if (GetPlayer()->isInCombat()) - reason = 1; - else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING)) - reason = 3; // is jumping or falling - else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command - reason = 2; // FIXME - Need the correct value - - if (reason) - { - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(reason); - data << uint32(0); - SendPacket(&data); - LogoutRequest(0); - return; - } - - //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf - if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight() || - GetSecurity() >= AccountTypes(sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT))) - { - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(0); - data << uint32(16777216); - SendPacket(&data); - LogoutPlayer(true); - return; - } - - // not set flags if player can't free move to prevent lost state at logout cancel - if (GetPlayer()->CanFreeMove()) - { - GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); - - WorldPacket data(SMSG_MOVE_ROOT, (8+4)); // guess size - data.append(GetPlayer()->GetPackGUID()); - data << (uint32)2; - SendPacket(&data); - GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - } - - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(0); - data << uint32(0); - SendPacket(&data); - LogoutRequest(time(NULL)); -} - -void WorldSession::HandlePlayerLogoutOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_PLAYER_LOGOUT Message"); -} - -void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); - - LogoutRequest(0); - - WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0); - SendPacket(&data); - - // not remove flags if can't free move - its not set in Logout request code. - if (GetPlayer()->CanFreeMove()) - { - //!we can move again - data.Initialize(SMSG_MOVE_UNROOT, 8); // guess size - data.append(GetPlayer()->GetPackGUID()); - data << uint32(0); - SendPacket(&data); - - //! Stand Up - GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND); - - //! DISABLE_ROTATE - GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LOGOUT_CANCEL_ACK Message"); -} - -void WorldSession::HandleTogglePvP(WorldPacket & recv_data) -{ - // this opcode can be used in two ways: Either set explicit new status or toggle old status - if (recv_data.size() == 1) - { - bool newPvPStatus; - recv_data >> newPvPStatus; - GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); - GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus); - } - else - { - GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); - GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER); - } - - if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) - { - if (!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.endTimer != 0) - GetPlayer()->UpdatePvP(true, true); - } - else - { - if (!GetPlayer()->pvpInfo.inHostileArea && GetPlayer()->IsPvP()) - GetPlayer()->pvpInfo.endTimer = time(NULL); // start toggle-off - } - - //if (OutdoorPvP* pvp = _player->GetOutdoorPvP()) - // pvp->HandlePlayerActivityChanged(_player); -} - -void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) -{ - uint32 newZone; - recv_data >> newZone; - - sLog->outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); - - // use server size data - uint32 newzone, newarea; - GetPlayer()->GetZoneAndAreaId(newzone, newarea); - GetPlayer()->UpdateZone(newzone, newarea); - //GetPlayer()->SendInitWorldStates(true, newZone); -} - -void WorldSession::HandleReturnToGraveyard(WorldPacket& /*recvPacket*/) -{ - if (GetPlayer()->isAlive() || !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - return; - GetPlayer()->RepopAtGraveyard(); -} - -void WorldSession::HandleSetSelectionOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - _player->SetSelection(guid); -} - -void WorldSession::HandleStandStateChangeOpcode(WorldPacket & recv_data) -{ - // sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_STANDSTATECHANGE"); -- too many spam in log at lags/debug stop - uint32 animstate; - recv_data >> animstate; - - _player->SetStandState(animstate); -} - -void WorldSession::HandleContactListOpcode(WorldPacket & recv_data) -{ - uint32 unk; - recv_data >> unk; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", unk); - _player->GetSocial()->SendSocialList(_player); -} - -void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_FRIEND"); - - std::string friendName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); - std::string friendNote; - - recv_data >> friendName; - - recv_data >> friendNote; - - if (!normalizePlayerName(friendName)) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName(), friendName.c_str()); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME); - - stmt->setString(0, friendName); - - _addFriendCallback.SetParam(friendNote); - _addFriendCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); -} - -void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std::string friendNote) -{ - if (!GetPlayer()) - return; - - uint64 friendGuid; - uint32 friendAccountId; - uint32 team; - FriendsResult friendResult; - - friendResult = FRIEND_NOT_FOUND; - friendGuid = 0; - - if (result) - { - Field* fields = result->Fetch(); - - friendGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - team = Player::TeamForRace(fields[1].GetUInt8()); - friendAccountId = fields[2].GetUInt32(); - - if (!AccountMgr::IsPlayerAccount(GetSecurity()) || sWorld->getBoolConfig(CONFIG_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realmID))) - { - if (friendGuid) - { - if (friendGuid == GetPlayer()->GetGUID()) - friendResult = FRIEND_SELF; - else if (GetPlayer()->GetTeam() != team && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && AccountMgr::IsPlayerAccount(GetSecurity())) - friendResult = FRIEND_ENEMY; - else if (GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) - friendResult = FRIEND_ALREADY; - else - { - Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); - if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer())) - friendResult = FRIEND_ADDED_ONLINE; - else - friendResult = FRIEND_ADDED_OFFLINE; - if (!GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) - { - friendResult = FRIEND_LIST_FULL; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s's friend list is full.", GetPlayer()->GetName()); - } - } - GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); - } - } - } - - sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleDelFriendOpcode(WorldPacket & recv_data) -{ - uint64 FriendGUID; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DEL_FRIEND"); - - recv_data >> FriendGUID; - - _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); - - sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ADD_IGNORE"); - - std::string ignoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); - - recv_data >> ignoreName; - - if (!normalizePlayerName(ignoreName)) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to Ignore: '%s'", - GetPlayer()->GetName(), ignoreName.c_str()); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME); - - stmt->setString(0, ignoreName); - - _addIgnoreCallback = CharacterDatabase.AsyncQuery(stmt); -} - -void WorldSession::HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result) -{ - if (!GetPlayer()) - return; - - uint64 IgnoreGuid; - FriendsResult ignoreResult; - - ignoreResult = FRIEND_IGNORE_NOT_FOUND; - IgnoreGuid = 0; - - if (result) - { - IgnoreGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); - - if (IgnoreGuid) - { - if (IgnoreGuid == GetPlayer()->GetGUID()) //not add yourself - ignoreResult = FRIEND_IGNORE_SELF; - else if (GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid))) - ignoreResult = FRIEND_IGNORE_ALREADY; - else - { - ignoreResult = FRIEND_IGNORE_ADDED; - - // ignore list full - if (!GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) - ignoreResult = FRIEND_IGNORE_FULL; - } - } - } - - sSocialMgr->SendFriendStatus(GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleDelIgnoreOpcode(WorldPacket & recv_data) -{ - uint64 IgnoreGUID; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DEL_IGNORE"); - - recv_data >> IgnoreGUID; - - _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); - - sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent motd (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleSetContactNotesOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_CONTACT_NOTES"); - uint64 guid; - std::string note; - recv_data >> guid >> note; - _player->GetSocial()->SetFriendNote(GUID_LOPART(guid), note); -} - -void WorldSession::HandleBugOpcode(WorldPacket & recv_data) -{ - uint32 suggestion, contentlen, typelen; - std::string content, type; - - recv_data >> suggestion >> contentlen >> content; - - recv_data >> typelen >> type; - - if (suggestion == 0) - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUG [Bug Report]"); - else - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BUG [Suggestion]"); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", type.c_str()); - sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", content.c_str()); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_BUG_REPORT); - - stmt->setString(0, type); - stmt->setString(1, content); - - CharacterDatabase.Execute(stmt); -} - -void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) -{ - sLog->outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); - - uint64 guid; - recv_data >> guid; - - if (GetPlayer()->isAlive()) - return; - - // do not allow corpse reclaim in arena - if (GetPlayer()->InArena()) - return; - - // body not released yet - if (!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - return; - - Corpse* corpse = GetPlayer()->GetCorpse(); - - if (!corpse) - return; - - // prevent resurrect before 30-sec delay after body release not finished - if (time_t(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP)) > time_t(time(NULL))) - return; - - if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) - return; - - // resurrect - GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleground() ? 1.0f : 0.5f); - - // spawn bones - GetPlayer()->SpawnCorpseBones(); -} - -void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) -{ - sLog->outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); - - uint64 guid; - uint8 status; - recv_data >> guid; - recv_data >> status; - - if (GetPlayer()->isAlive()) - return; - - if (status == 0) - { - GetPlayer()->clearResurrectRequestData(); // reject - return; - } - - if (!GetPlayer()->isRessurectRequestedBy(guid)) - return; - - GetPlayer()->ResurectUsingRequestData(); -} - -void WorldSession::SendAreaTriggerMessage(const char* Text, ...) -{ - va_list ap; - char szStr [1024]; - szStr[0] = '\0'; - - va_start(ap, Text); - vsnprintf(szStr, 1024, Text, ap); - va_end(ap); - - uint32 length = strlen(szStr)+1; - WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 4+length); - data << length; - data << szStr; - SendPacket(&data); -} - -void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) -{ - uint32 triggerId; - recv_data >> triggerId; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_AREATRIGGER. Trigger ID: %u", triggerId); - - Player* player = GetPlayer(); - if (player->isInFlight()) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u", - player->GetName(), player->GetGUIDLow(), triggerId); - return; - } - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(triggerId); - if (!atEntry) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) send unknown (by DBC) Area Trigger ID:%u", - player->GetName(), player->GetGUIDLow(), triggerId); - return; - } - - if (player->GetMapId() != atEntry->mapid) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u", - player->GetName(), atEntry->mapid, player->GetMapId(), player->GetGUIDLow(), triggerId); - return; - } - - // delta is safe radius - const float delta = 5.0f; - - if (atEntry->radius > 0) - { - // if we have radius check it - float dist = player->GetDistance(atEntry->x, atEntry->y, atEntry->z); - if (dist > atEntry->radius + delta) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) too far (radius: %f distance: %f), ignore Area Trigger ID: %u", - player->GetName(), player->GetGUIDLow(), atEntry->radius, dist, triggerId); - return; - } - } - else - { - // we have only extent - - // rotate the players position instead of rotating the whole cube, that way we can make a simplified - // is-in-cube check and we have to calculate only one point instead of 4 - - // 2PI = 360°, keep in mind that ingame orientation is counter-clockwise - double rotation = 2 * M_PI - atEntry->box_orientation; - double sinVal = sin(rotation); - double cosVal = cos(rotation); - - float playerBoxDistX = player->GetPositionX() - atEntry->x; - float playerBoxDistY = player->GetPositionY() - atEntry->y; - - float rotPlayerX = float(atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal); - float rotPlayerY = float(atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal); - - // box edges are parallel to coordiante axis, so we can treat every dimension independently :D - float dz = player->GetPositionZ() - atEntry->z; - float dx = rotPlayerX - atEntry->x; - float dy = rotPlayerY - atEntry->y; - if ((fabs(dx) > atEntry->box_x / 2 + delta) || - (fabs(dy) > atEntry->box_y / 2 + delta) || - (fabs(dz) > atEntry->box_z / 2 + delta)) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u", - player->GetName(), player->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, triggerId); - return; - } - } - - if (player->isDebugAreaTriggers) - ChatHandler(player).PSendSysMessage(LANG_DEBUG_AREATRIGGER_REACHED, triggerId); - - if (sScriptMgr->OnAreaTrigger(player, atEntry)) - return; - - if (player->isAlive()) - if (uint32 questId = sObjectMgr->GetQuestForAreaTrigger(triggerId)) - if (player->GetQuestStatus(questId) == QUEST_STATUS_INCOMPLETE) - player->AreaExploredOrEventHappens(questId); - - if (sObjectMgr->IsTavernAreaTrigger(triggerId)) - { - // set resting flag we are in the inn - player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - player->InnEnter(time(NULL), atEntry->mapid, atEntry->x, atEntry->y, atEntry->z); - player->SetRestType(REST_TYPE_IN_TAVERN); - - if (sWorld->IsFFAPvPRealm()) - player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - - return; - } - - if (Battleground* bg = player->GetBattleground()) - if (bg->GetStatus() == STATUS_IN_PROGRESS) - { - bg->HandleAreaTrigger(player, triggerId); - return; - } - - if (OutdoorPvP* pvp = player->GetOutdoorPvP()) - if (pvp->HandleAreaTrigger(_player, triggerId)) - return; - - AreaTrigger const* at = sObjectMgr->GetAreaTrigger(triggerId); - if (!at) - return; - - bool teleported = false; - if (player->GetMapId() != at->target_mapId) - { - if (!sMapMgr->CanPlayerEnter(at->target_mapId, player, false)) - return; - - if (Group* group = player->GetGroup()) - if (group->isLFGGroup() && player->GetMap()->IsDungeon()) - teleported = player->TeleportToBGEntryPoint(); - } - - if (!teleported) - player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT); -} - -void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) -{ - sLog->outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); - - uint32 type, timestamp, decompressedSize; - recv_data >> type >> timestamp >> decompressedSize; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); - - if (type > NUM_ACCOUNT_DATA_TYPES) - return; - - if (decompressedSize == 0) // erase - { - SetAccountData(AccountDataType(type), 0, ""); - - WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); - data << uint32(type); - data << uint32(0); - SendPacket(&data); - - return; - } - - if (decompressedSize > 0xFFFF) - { - recv_data.rfinish(); // unnneded warning spam in this case - sLog->outError("UAD: Account data packet too big, size %u", decompressedSize); - return; - } - - ByteBuffer dest; - dest.resize(decompressedSize); - - uLongf realSize = decompressedSize; - if (uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) - { - recv_data.rfinish(); // unnneded warning spam in this case - sLog->outError("UAD: Failed to decompress account data"); - return; - } - - recv_data.rfinish(); // uncompress read (recv_data.size() - recv_data.rpos()) - - std::string adata; - dest >> adata; - - SetAccountData(AccountDataType(type), timestamp, adata); - - WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); - data << uint32(type); - data << uint32(0); - SendPacket(&data); -} - -void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) -{ - sLog->outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); - - uint32 type; - recv_data >> type; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "RAD: type %u", type); - - if (type > NUM_ACCOUNT_DATA_TYPES) - return; - - AccountData* adata = GetAccountData(AccountDataType(type)); - - uint32 size = adata->Data.size(); - - uLongf destSize = compressBound(size); - - ByteBuffer dest; - dest.resize(destSize); - - if (size && compress(const_cast<uint8*>(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "RAD: Failed to compress account data"); - return; - } - - dest.resize(destSize); - - WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize); - data << uint64(_player ? _player->GetGUID() : 0); // player guid - data << uint32(type); // type (0-7) - data << uint32(adata->Time); // unix time - data << uint32(size); // decompressed length - data.append(dest); // compressed data - SendPacket(&data); -} - -void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SET_ACTION_BUTTON"); - uint8 button; - uint32 packetData; - recv_data >> button >> packetData; - - uint32 action = ACTION_BUTTON_ACTION(packetData); - uint8 type = ACTION_BUTTON_TYPE(packetData); - - sLog->outDetail("BUTTON: %u ACTION: %u TYPE: %u", button, action, type); - if (!packetData) - { - sLog->outDetail("MISC: Remove action from button %u", button); - GetPlayer()->removeActionButton(button); - } - else - { - switch (type) - { - case ACTION_BUTTON_MACRO: - case ACTION_BUTTON_CMACRO: - sLog->outDetail("MISC: Added Macro %u into button %u", action, button); - break; - case ACTION_BUTTON_EQSET: - sLog->outDetail("MISC: Added EquipmentSet %u into button %u", action, button); - break; - case ACTION_BUTTON_SPELL: - sLog->outDetail("MISC: Added Spell %u into button %u", action, button); - break; - case ACTION_BUTTON_ITEM: - sLog->outDetail("MISC: Added Item %u into button %u", action, button); - break; - default: - sLog->outError("MISC: Unknown action button type %u for action %u into button %u", type, action, button); - return; - } - GetPlayer()->addActionButton(button, action, type); - } -} - -void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) -{ - sLog->outStaticDebug("WORLD: Player is watching cinema"); -} - -void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) -{ - sLog->outStaticDebug("WORLD: Which movie to play"); -} - -void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_TIME_SKIPPED"); - - BitStream mask = recv_data.ReadBitStream(8); - - uint32 time; - recv_data >> time; - - ByteBuffer bytes(8, true); - recv_data.ReadXorByte(mask[0], bytes[1]); - recv_data.ReadXorByte(mask[1], bytes[4]); - recv_data.ReadXorByte(mask[7], bytes[2]); - recv_data.ReadXorByte(mask[5], bytes[5]); - recv_data.ReadXorByte(mask[3], bytes[0]); - recv_data.ReadXorByte(mask[6], bytes[7]); - recv_data.ReadXorByte(mask[2], bytes[6]); - recv_data.ReadXorByte(mask[4], bytes[3]); - - uint64 guid = BitConverter::ToUInt64(bytes); - - //TODO! - - /* - uint64 guid; - uint32 time_skipped; - recv_data >> guid; - recv_data >> time_skipped; - sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_MOVE_TIME_SKIPPED"); - - /// TODO - must be need use in Trinity - We substract server Lags to move time (AntiLags) - for exmaple - GetPlayer()->ModifyLastMoveTime(-int32(time_skipped)); - */ -} - -void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) -{ - sLog->outStaticDebug("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); - - // no used - recv_data.rfinish(); // prevent warnings spam -} - -void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data) -{ - // no used - recv_data.rfinish(); // prevent warnings spam -/* - uint64 guid; - recv_data >> guid; - - // now can skip not our packet - if (_player->GetGUID() != guid) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK"); - - recv_data.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - recv_data.read_skip<float>(); // unk2 -*/ -} - -void WorldSession::HandleMoveRootAck(WorldPacket& recv_data) -{ - // no used - recv_data.rfinish(); // prevent warnings spam -/* - uint64 guid; - recv_data >> guid; - - // now can skip not our packet - if (_player->GetGUID() != guid) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_FORCE_MOVE_ROOT_ACK"); - - recv_data.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); -*/ -} - -void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) -{ - uint8 ActionBar; - - recv_data >> ActionBar; - - if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) - { - if (ActionBar != 0) - sLog->outError("WorldSession::HandleSetActionBarToggles in not logged state with value: %u, ignored", uint32(ActionBar)); - return; - } - - GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, ActionBar); -} - -void WorldSession::HandleWardenDataOpcode(WorldPacket& recv_data) -{ - recv_data.read_skip<uint8>(); - /* - uint8 tmp; - recv_data >> tmp; - sLog->outDebug("Received opcode CMSG_WARDEN_DATA, not resolve.uint8 = %u", tmp); - */ -} - -void WorldSession::HandlePlayedTime(WorldPacket& recv_data) -{ - uint8 unk1; - recv_data >> unk1; // 0 or 1 expected - - WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1); - data << uint32(_player->GetTotalPlayedTime()); - data << uint32(_player->GetLevelPlayedTime()); - data << uint8(unk1); // 0 - will not show in chat frame - SendPacket(&data); -} - -void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) -{ - uint64 guid; - recv_data >> guid; - sLog->outStaticDebug("Inspected guid is " UI64FMTD, guid); - - _player->SetSelection(guid); - - Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) // wrong player - return; - - uint32 talent_points = 41; - uint32 guid_size = player->GetPackGUID().wpos(); - WorldPacket data(SMSG_INSPECT_TALENT, guid_size+4+talent_points); - data.append(player->GetPackGUID()); - - if (sWorld->getBoolConfig(CONFIG_TALENTS_INSPECTING) || _player->isGameMaster()) - { - player->BuildPlayerTalentsInfoData(&data); - } - else - { - data << uint32(0); // unspentTalentPoints - data << uint8(0); // talentGroupCount - data << uint8(0); // talentGroupIndex - } - - player->BuildEnchantmentsInfoData(&data); - SendPacket(&data); -} - -void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) -{ - uint64 guid; - recv_data >> guid; - - Player* player = ObjectAccessor::FindPlayer(guid); - - if (!player) - { - sLog->outError("InspectHonorStats: WTF, player not found..."); - return; - } - - WorldPacket data(SMSG_INSPECT_HONOR_STATS, 4+1+4+8); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); - data << uint8(0); // rank - data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); - data << uint64(player->GetGUID()); - SendPacket(&data); -} - -void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) -{ - // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 - // Received opcode CMSG_WORLD_TELEPORT - // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 - - uint32 time; - uint32 mapid; - float PositionX; - float PositionY; - float PositionZ; - float Orientation; - - recv_data >> time; // time in m.sec. - recv_data >> mapid; - recv_data >> PositionX; - recv_data >> PositionY; - recv_data >> PositionZ; - recv_data >> Orientation; // o (3.141593 = 180 degrees) - - //sLog->outDebug("Received opcode CMSG_WORLD_TELEPORT"); - if (GetPlayer()->isInFlight()) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) in flight, ignore worldport command.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - return; - } - - sLog->outStaticDebug("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); - - if (AccountMgr::IsAdminAccount(GetSecurity())) - GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation); - else - SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received worldport command from player %s", GetPlayer()->GetName()); -} - -void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_WHOIS"); - std::string charname; - recv_data >> charname; - - if (!AccountMgr::IsAdminAccount(GetSecurity())) - { - SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - return; - } - - if (charname.empty() || !normalizePlayerName (charname)) - { - SendNotification(LANG_NEED_CHARACTER_NAME); - return; - } - - Player* player = sObjectAccessor->FindPlayerByName(charname.c_str()); - - if (!player) - { - SendNotification(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, charname.c_str()); - return; - } - - uint32 accid = player->GetSession()->GetAccountId(); - - QueryResult result = LoginDatabase.PQuery("SELECT username, email, last_ip FROM account WHERE id=%u", accid); - if (!result) - { - SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str()); - return; - } - - Field* fields = result->Fetch(); - std::string acc = fields[0].GetString(); - if (acc.empty()) - acc = "Unknown"; - std::string email = fields[1].GetString(); - if (email.empty()) - email = "Unknown"; - std::string lastip = fields[2].GetString(); - if (lastip.empty()) - lastip = "Unknown"; - - std::string msg = charname + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; - - WorldPacket data(SMSG_WHOIS, msg.size()+1); - data << msg; - _player->GetSession()->SendPacket(&data); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received whois command from player %s for character %s", GetPlayer()->GetName(), charname.c_str()); -} - -void WorldSession::HandleComplainOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_COMPLAIN"); - - uint8 spam_type; // 0 - mail, 1 - chat - uint64 spammer_guid; - uint32 unk1 = 0; - uint32 unk2 = 0; - uint32 unk3 = 0; - uint32 unk4 = 0; - std::string description = ""; - recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat) - recv_data >> spammer_guid; // player guid - switch (spam_type) - { - case 0: - recv_data >> unk1; // const 0 - recv_data >> unk2; // probably mail id - recv_data >> unk3; // const 0 - break; - case 1: - recv_data >> unk1; // probably language - recv_data >> unk2; // message type? - recv_data >> unk3; // probably channel id - recv_data >> unk4; // unk random value - recv_data >> description; // spam description string (messagetype, channel name, player name, message) - break; - } - - // NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam. - // if it's mail spam - ALL mails from this spammer automatically removed by client - - // Complaint Received message - WorldPacket data(SMSG_COMPLAIN_RESULT, 2); - data << uint8(0); // value 1 resets CGChat::m_complaintsSystemStatus in client. (unused?) - data << uint8(0); // value 0xC generates a "CalendarError" in client. - SendPacket(&data); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "REPORT SPAM: type %u, guid %u, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s", spam_type, GUID_LOPART(spammer_guid), unk1, unk2, unk3, unk4, description.c_str()); -} - -void WorldSession::HandleRealmSplitOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_REALM_SPLIT"); - - uint32 unk; - std::string split_date = "01/01/01"; - recv_data >> unk; - - WorldPacket data(SMSG_REALM_SPLIT, 4+4+split_date.size()+1); - data << unk; - data << uint32(0x00000000); // realm split state - // split states: - // 0x0 realm normal - // 0x1 realm split - // 0x2 realm split pending - data << split_date; - SendPacket(&data); - //sLog->outDebug("response sent %u", unk); -} - -void WorldSession::HandleFarSightOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_FAR_SIGHT"); - - uint8 apply; - recv_data >> apply; - - switch (apply) - { - case 0: - sLog->outDebug(LOG_FILTER_NETWORKIO, "Player %u set vision to self", _player->GetGUIDLow()); - _player->SetSeer(_player); - break; - case 1: - sLog->outDebug(LOG_FILTER_NETWORKIO, "Added FarSight " UI64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow()); - if (WorldObject* target = _player->GetViewpoint()) - _player->SetSeer(target); - else - sLog->outError("Player %s requests non-existing seer " UI64FMTD, _player->GetName(), _player->GetUInt64Value(PLAYER_FARSIGHT)); - break; - default: - sLog->outDebug(LOG_FILTER_NETWORKIO, "Unhandled mode in CMSG_FAR_SIGHT: %u", apply); - return; - } - - GetPlayer()->UpdateVisibilityForPlayer(); -} - -void WorldSession::HandleSetTitleOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_SET_TITLE"); - - int32 title; - recv_data >> title; - - // -1 at none - if (title > 0 && title < MAX_TITLE_INDEX) - { - if (!GetPlayer()->HasTitle(title)) - return; - } - else - title = 0; - - GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); -} - -void WorldSession::HandleTimeSyncResp(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_TIME_SYNC_RESP"); - - uint32 counter, clientTicks; - recv_data >> clientTicks >> counter; - - if (counter != _player->m_timeSyncCounter - 1) - sLog->outDebug(LOG_FILTER_NETWORKIO, "Wrong time sync counter from player %s (cheater?)", _player->GetName()); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient); - - uint32 ourTicks = clientTicks + (getMSTime() - _player->m_timeSyncServer); - - // diff should be small - sLog->outDebug(LOG_FILTER_NETWORKIO, "Our ticks: %u, diff %u, latency %u", ourTicks, ourTicks - clientTicks, GetLatency()); - - _player->m_timeSyncClient = clientTicks; -} - -void WorldSession::HandleResetInstancesOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_RESET_INSTANCES"); - Group* group = _player->GetGroup(); - if (group) - { - if (group->IsLeader(_player->GetGUID())) - { - group->ResetInstances(INSTANCE_RESET_ALL, false, _player); - group->ResetInstances(INSTANCE_RESET_ALL, true, _player); - } - } - else - { - _player->ResetInstances(INSTANCE_RESET_ALL, false); - _player->ResetInstances(INSTANCE_RESET_ALL, true); - } -} - -void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_SET_DUNGEON_DIFFICULTY"); - - uint32 mode; - recv_data >> mode; - - if (mode >= MAX_DUNGEON_DIFFICULTY) - { - sLog->outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); - return; - } - - if (Difficulty(mode) == _player->GetDungeonDifficulty()) - return; - - // cannot reset while in an instance - Map* map = _player->GetMap(); - if (map && map->IsDungeon()) - { - sLog->outError("WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!", _player->GetName(), _player->GetGUIDLow()); - return; - } - - Group* group = _player->GetGroup(); - if (group) - { - if (group->IsLeader(_player->GetGUID())) - { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pGroupGuy = itr->getSource(); - if (!pGroupGuy) - continue; - - if (!pGroupGuy->IsInMap(pGroupGuy)) - return; - - map = pGroupGuy->GetMap(); - if (map && map->IsNonRaidDungeon()) - { - sLog->outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!", _player->GetGUIDLow(), pGroupGuy->GetName(), pGroupGuy->GetGUIDLow()); - return; - } - } - // the difficulty is set even if the instances can't be reset - //_player->SendDungeonDifficulty(true); - group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player); - group->SetDungeonDifficulty(Difficulty(mode)); - } - } - else - { - _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false); - _player->SetDungeonDifficulty(Difficulty(mode)); - } -} - -void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_SET_RAID_DIFFICULTY"); - - uint32 mode; - recv_data >> mode; - - if (mode >= MAX_RAID_DIFFICULTY) - { - sLog->outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); - return; - } - - // cannot reset while in an instance - Map* map = _player->GetMap(); - if (map && map->IsDungeon()) - { - sLog->outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); - return; - } - - if (Difficulty(mode) == _player->GetRaidDifficulty()) - return; - - Group* group = _player->GetGroup(); - if (group) - { - if (group->IsLeader(_player->GetGUID())) - { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pGroupGuy = itr->getSource(); - if (!pGroupGuy) - continue; - - if (!pGroupGuy->IsInMap(pGroupGuy)) - return; - - map = pGroupGuy->GetMap(); - if (map && map->IsRaid()) - { - sLog->outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); - return; - } - } - // the difficulty is set even if the instances can't be reset - //_player->SendDungeonDifficulty(true); - group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, _player); - group->SetRaidDifficulty(Difficulty(mode)); - } - } - else - { - _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true); - _player->SetRaidDifficulty(Difficulty(mode)); - } -} - -void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CANCEL_MOUNT_AURA"); - - //If player is not mounted, so go out :) - if (!_player->IsMounted()) // not blizz like; no any messages on blizz - { - ChatHandler(this).SendSysMessage(LANG_CHAR_NON_MOUNTED); - return; - } - - if (_player->isInFlight()) // not blizz like; no any messages on blizz - { - ChatHandler(this).SendSysMessage(LANG_YOU_IN_FLIGHT); - return; - } - - _player->Dismount(); - _player->RemoveAurasByType(SPELL_AURA_MOUNTED); -} - -void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recv_data) -{ - // fly mode on/off - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); - - uint64 guid; // guid - unused - recv_data.readPackGUID(guid); - - recv_data.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip<float>(); // unk2 - - _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); -} - -void WorldSession::HandleRequestPetInfoOpcode(WorldPacket & /*recv_data */) -{ - /* - sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_REQUEST_PET_INFO"); - recv_data.hexlike(); - */ -} - -void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket & recv_data) -{ - uint8 mode; - recv_data >> mode; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Client used \"/timetest %d\" command", mode); -} - -void WorldSession::HandleQueryInspectAchievements(WorldPacket & recv_data) -{ - uint64 guid; - recv_data.readPackGUID(guid); - - Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) - return; - - player->GetAchievementMgr().SendRespondInspectAchievements(_player); -} - -void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recv_data*/) -{ - // empty opcode - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE"); - - WorldPacket data(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4); - data << uint32(time(NULL)); - SendPacket(&data); -} - -void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recv_data*/) -{ - // empty opcode - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_READY_FOR_ACCOUNT_DATA_TIMES"); - - SendAccountDataTimes(GLOBAL_CACHE_MASK); -} - -void WorldSession::SendSetPhaseShift(uint32 PhaseShift) -{ - WorldPacket data(SMSG_SET_PHASE_SHIFT, 4); - data << uint32(PhaseShift); - SendPacket(&data); -} - -void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recv_data*/) -{ - if (_player->isInFlight()) - return; - - AreaTableEntry const* atEntry = GetAreaEntryByAreaID(_player->GetAreaId()); - if (!atEntry || !(atEntry->flags & AREA_FLAG_WINTERGRASP_2)) - return; - - _player->BuildPlayerRepop(); - _player->ResurrectPlayer(100); - _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); -} - -void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket) -{ - uint8 accept; - recvPacket >> accept; - - if (!_player->HasPendingBind()) - { - sLog->outDetail("InstanceLockResponse: Player %s (guid %u) tried to bind himself/teleport to graveyard without a pending bind!", _player->GetName(), _player->GetGUIDLow()); - return; - } - - if (accept) - _player->BindToInstance(); - else - _player->RepopAtGraveyard(); - - _player->SetPendingBind(0, 0); -} diff --git a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp deleted file mode 100755 index 71dfc670145..00000000000 --- a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp +++ /dev/null @@ -1,915 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "Corpse.h" -#include "Player.h" -#include "SpellAuras.h" -#include "MapManager.h" -#include "Transport.h" -#include "Battleground.h" -#include "WaypointMovementGenerator.h" -#include "InstanceSaveMgr.h" -#include "ObjectMgr.h" -#include "MovementStructures.h" - -void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: got CMSG_WORLD_PORT_RESPONSE."); - HandleMoveWorldportAckOpcode(); -} - -void WorldSession::HandleMoveWorldportAckOpcode() -{ - // ignore unexpected far teleports - if (!GetPlayer()->IsBeingTeleportedFar()) - return; - - GetPlayer()->SetSemaphoreTeleportFar(false); - - // get the teleport destination - WorldLocation &loc = GetPlayer()->GetTeleportDest(); - - // possible errors in the coordinate validity check - if (!MapManager::IsValidMapCoord(loc)) - { - LogoutPlayer(false); - return; - } - - // get the destination map entry, not the current one, this will fix homebind and reset greeting - MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); - InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId()); - - // reset instance validity, except if going to an instance inside an instance - if (GetPlayer()->m_InstanceValid == false && !mInstance) - GetPlayer()->m_InstanceValid = true; - - Map* oldMap = GetPlayer()->GetMap(); - ASSERT(oldMap); - if (GetPlayer()->IsInWorld()) - { - sLog->outCrash("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId()); - oldMap->RemovePlayerFromMap(GetPlayer(), false); - } - - // relocate the player to the teleport destination - Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer()); - // the CanEnter checks are done in TeleporTo but conditions may change - // while the player is in transit, for example the map may get full - if (!newMap || !newMap->CanEnter(GetPlayer())) - { - sLog->outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); - GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); - return; - } - else - GetPlayer()->Relocate(&loc); - - GetPlayer()->ResetMap(); - GetPlayer()->SetMap(newMap); - - GetPlayer()->SendInitialPacketsBeforeAddToMap(); - if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer())) - { - sLog->outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); - GetPlayer()->ResetMap(); - GetPlayer()->SetMap(oldMap); - GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); - return; - } - - // battleground state prepare (in case join to BG), at relogin/tele player not invited - // only add to bg group and object, if the player was invited (else he entered through command) - if (_player->InBattleground()) - { - // cleanup setting if outdated - if (!mEntry->IsBattlegroundOrArena()) - { - // We're not in BG - _player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE); - // reset destination bg team - _player->SetBGTeam(0); - } - // join to bg case - else if (Battleground* bg = _player->GetBattleground()) - { - if (_player->IsInvitedForBattlegroundInstance(_player->GetBattlegroundId())) - bg->AddPlayer(_player); - } - } - - GetPlayer()->SendInitialPacketsAfterAddToMap(); - - // flight fast teleport case - if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) - { - if (!_player->InBattleground()) - { - // short preparations to continue flight - FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - flight->Initialize(*GetPlayer()); - return; - } - - // battleground state prepare, stop flight - GetPlayer()->GetMotionMaster()->MovementExpired(); - GetPlayer()->CleanupAfterTaxiFlight(); - } - - // resurrect character at enter into instance where his corpse exist after add to map - Corpse* corpse = GetPlayer()->GetCorpse(); - if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) - { - if (mEntry->IsDungeon()) - { - GetPlayer()->ResurrectPlayer(0.5f, false); - GetPlayer()->SpawnCorpseBones(); - } - } - - bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); - if (mInstance) - { - Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); - if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff)) - { - if (mapDiff->resetTime) - { - if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff)) - { - uint32 timeleft = uint32(timeReset - time(NULL)); - GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft); - } - } - } - allowMount = mInstance->AllowMount; - } - - // mount allow check - if (!allowMount) - _player->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // update zone immediately, otherwise leave channel will cause crash in mtmap - uint32 newzone, newarea; - GetPlayer()->GetZoneAndAreaId(newzone, newarea); - GetPlayer()->UpdateZone(newzone, newarea); - - // honorless target - if (GetPlayer()->pvpInfo.inHostileArea) - GetPlayer()->CastSpell(GetPlayer(), 2479, true); - - // in friendly area - else if (GetPlayer()->IsPvP() && !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) - GetPlayer()->UpdatePvP(false, false); - - // resummon pet - GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); - - //lets process all delayed operations on successful teleport - GetPlayer()->ProcessDelayedOperations(); -} - -void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_TELEPORT_ACK"); - - BitStream mask = recv_data.ReadBitStream(8); - - uint32 flags, time; - recv_data >> flags >> time; - - ByteBuffer bytes(8, true); - recv_data.ReadXorByte(mask[6], bytes[1]); - recv_data.ReadXorByte(mask[0], bytes[3]); - recv_data.ReadXorByte(mask[1], bytes[2]); - recv_data.ReadXorByte(mask[7], bytes[0]); - recv_data.ReadXorByte(mask[5], bytes[6]); - recv_data.ReadXorByte(mask[3], bytes[4]); - recv_data.ReadXorByte(mask[2], bytes[7]); - recv_data.ReadXorByte(mask[4], bytes[5]); - - uint64 guid = BitConverter::ToUInt64(bytes); - - sLog->outStaticDebug("Guid " UI64FMTD, guid); - sLog->outStaticDebug("Flags %u, time %u", flags, time/IN_MILLISECONDS); - - Unit* mover = _player->m_mover; - Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; - - if (!plMover || !plMover->IsBeingTeleportedNear()) - return; - - if (guid != plMover->GetGUID()) - return; - - plMover->SetSemaphoreTeleportNear(false); - - uint32 old_zone = plMover->GetZoneId(); - - WorldLocation const& dest = plMover->GetTeleportDest(); - - plMover->UpdatePosition(dest, true); - - uint32 newzone, newarea; - plMover->GetZoneAndAreaId(newzone, newarea); - plMover->UpdateZone(newzone, newarea); - - // new zone - if (old_zone != newzone) - { - // honorless target - if (plMover->pvpInfo.inHostileArea) - plMover->CastSpell(plMover, 2479, true); - - // in friendly area - else if (plMover->IsPvP() && !plMover->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) - plMover->UpdatePvP(false, false); - } - - // resummon pet - GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); - - //lets process all delayed operations on successful teleport - GetPlayer()->ProcessDelayedOperations(); -} - -void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) -{ - uint16 opcode = recv_data.GetOpcode(); - - Unit* mover = _player->m_mover; - - ASSERT(mover != NULL); // there must always be a mover - - Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; - - // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck - if (plMover && plMover->IsBeingTeleported()) - { - return; - } - - /* extract packet */ - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); - - // prevent tampered movement data - if (movementInfo.guid != mover->GetGUID()) - { - sLog->outError("HandleMovementOpcodes: guid error"); - return; - } - if (!movementInfo.pos.IsPositionValid()) - { - sLog->outError("HandleMovementOpcodes: Invalid Position"); - return; - } - - /* handle special cases */ - if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) - { - // transports size limited - // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) - if (movementInfo.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(), - movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation())) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - // if we boarded a transport, add us to it - if (plMover && !plMover->GetTransport()) - { - // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list - for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) - { - if ((*iter)->GetGUID() == movementInfo.t_guid) - { - plMover->m_transport = (*iter); - (*iter)->AddPassenger(plMover); - break; - } - } - } - - if (!mover->GetTransport() && !mover->GetVehicle()) - { - GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid); - if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) - movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; - } - } - else if (plMover && plMover->GetTransport()) // if we were on a transport, leave - { - plMover->m_transport->RemovePassenger(plMover); - plMover->m_transport = NULL; - movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); - movementInfo.t_time = 0; - movementInfo.t_seat = -1; - } - - // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight()) - plMover->HandleFall(movementInfo); - - if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater()) - { - // now client not include swimming flag in case jumping under water - plMover->SetInWater(!plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); - } - - /*----------------------*/ - - /* process position-change */ - WorldPacket data(SMSG_PLAYER_MOVE, recv_data.size()); - movementInfo.time = getMSTime(); - movementInfo.guid = mover->GetGUID(); - WriteMovementInfo(data, &movementInfo); - mover->SendMessageToSet(&data, _player); - - mover->m_movementInfo = movementInfo; - - // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() - if (mover->GetVehicle()) - { - mover->SetOrientation(movementInfo.pos.GetOrientation()); - return; - } - - mover->UpdatePosition(movementInfo.pos); - - if (plMover) // nothing is charmed, or player charmed - { - plMover->UpdateFallInformationIfNeed(movementInfo, opcode); - - if (movementInfo.pos.GetPositionZ() < -500.0f) - { - if (!(plMover->InBattleground() - && plMover->GetBattleground() - && plMover->GetBattleground()->HandlePlayerUnderMap(_player))) - { - // NOTE: this is actually called many times while falling - // even after the player has been teleported away - // TODO: discard movement packets after the player is rooted - if (plMover->isAlive()) - { - plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // player can be alive if GM/etc - // change the death state to CORPSE to prevent the death timer from - // starting in the next player update - if (!plMover->isAlive()) - plMover->KillPlayer(); - } - } - } - } -} - -void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) -{ - uint32 opcode = recv_data.GetOpcode(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(Opcodes(opcode)), opcode, opcode); - - /* extract packet */ - uint64 guid; - uint32 unk1; - float newspeed; - - recv_data.readPackGUID(guid); - - // now can skip not our packet - if (_player->GetGUID() != guid) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - // continue parse packet - - recv_data >> unk1; // counter or moveEvent - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data >> newspeed; - /*----------------*/ - - // client ACK send one packet for mounted/run case and need skip all except last from its - // in other cases anti-cheat check can be fail in false case - UnitMoveType move_type; - UnitMoveType force_move_type; - - static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; - - switch (opcode) - { - case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; - case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; - case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; - case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; - case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; - case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; - case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; - case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; - case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; - default: - sLog->outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); - return; - } - - // skip all forced speed changes except last and unexpected - // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both. - if (_player->m_forced_speed_changes[force_move_type] > 0) - { - --_player->m_forced_speed_changes[force_move_type]; - if (_player->m_forced_speed_changes[force_move_type] > 0) - return; - } - - if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f) - { - if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct - { - sLog->outError("%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", - move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), newspeed); - _player->SetSpeed(move_type, _player->GetSpeedRate(move_type), true); - } - else // must be lesser - cheating - { - sLog->outBasic("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)", - _player->GetName(), _player->GetSession()->GetAccountId(), _player->GetSpeed(move_type), newspeed); - _player->GetSession()->KickPlayer(); - } - } -} - -void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); - - uint64 guid; - recv_data >> guid; - - if (GetPlayer()->IsInWorld()) - { - if (Unit* mover = ObjectAccessor::GetUnit(*GetPlayer(), guid)) - { - GetPlayer()->SetMover(mover); - if (mover != GetPlayer() && mover->canFly()) - { - GetPlayer()->SendSetFlyPacket(true); - } - } - else - { - sLog->outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, guid, GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID()); - GetPlayer()->SetMover(GetPlayer()); - } - } -} - -void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); - - uint64 old_mover_guid; - recv_data.readPackGUID(old_mover_guid); - - MovementInfo mi; - mi.guid = old_mover_guid; - ReadMovementInfo(recv_data, &mi); - - _player->m_movementInfo = mi; -} - -void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recv_data*/) -{ - WorldPacket data(SMSG_MOUNTSPECIAL_ANIM, 8); - data << uint64(GetPlayer()->GetGUID()); - - GetPlayer()->SendMessageToSet(&data, false); -} - -void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_KNOCK_BACK_ACK"); - - uint64 guid; - recv_data.readPackGUID(guid); - - if (_player->m_mover->GetGUID() != guid) - return; - - recv_data.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); - _player->m_movementInfo = movementInfo; - - WorldPacket data(SMSG_MOVE_UPDATE_KNOCK_BACK, 66); - data.appendPackGUID(guid); - _player->BuildMovementPacket(&data); - - // knockback specific info - data << movementInfo.j_sinAngle; - data << movementInfo.j_cosAngle; - data << movementInfo.j_xyspeed; - data << movementInfo.j_zspeed; - - _player->SendMessageToSet(&data, false); -} - -void WorldSession::HandleMoveHoverAck(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_HOVER_ACK"); - - uint64 guid; // guid - unused - recv_data.readPackGUID(guid); - - recv_data.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip<uint32>(); // unk2 -} - -void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_WATER_WALK_ACK"); - - uint64 guid; // guid - unused - recv_data.readPackGUID(guid); - - recv_data.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip<uint32>(); // unk2 -} - -void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data) -{ - if (!_player->isAlive() || _player->isInCombat()) - return; - - uint64 summonerGuid; - bool agree; - recv_data >> summonerGuid; - recv_data >> agree; - - _player->SummonIfPossible(agree); -} - -void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi) -{ - bool HaveTransportData = false, - HaveTransportTime2 = false, - HaveTransportTime3 = false, - HavePitch = false, - HaveFallData = false, - HaveFallDirection = false, - HaveSplineElevation = false, - HaveSpline = false; - - MovementStatusElements *sequence = GetMovementStatusElementsSequence(data.GetOpcode()); - if (sequence == NULL) - return; - - BytesGuid guid; - BytesGuid tguid; - - guid.guid = 0; - tguid.guid = 0; - - for (uint32 i = 0; i < MSE_COUNT; i++) - { - MovementStatusElements element = sequence[i]; - - if (element >= MSEGuidByte0 && element <= MSEGuidByte7) - { - data.ReadByteMask(guid.bytes[element - MSEGuidByte0]); - continue; - } - - if (element >= MSETransportGuidByte0 && - element <= MSETransportGuidByte7) - { - if (HaveTransportData) - data.ReadByteMask(tguid.bytes[element - MSETransportGuidByte0]); - continue; - } - - if (element >= MSEGuidByte0_2 && element <= MSEGuidByte7_2) - { - data.ReadByteSeq(guid.bytes[element - MSEGuidByte0_2]); - continue; - } - - if (element >= MSETransportGuidByte0_2 && - element <= MSETransportGuidByte7_2) - { - if (HaveTransportData) - data.ReadByteSeq(tguid.bytes[element - MSETransportGuidByte0_2]); - continue; - } - - switch (element) - { - case MSEFlags: - mi->flags = data.ReadBits(30); - break; - case MSEFlags2: - mi->flags2 = data.ReadBits(12); - break; - case MSETimestamp: - data >> mi->time; - break; - case MSEHavePitch: - HavePitch = data.ReadBit(); - break; - case MSEHaveFallData: - HaveFallData = data.ReadBit(); - break; - case MSEHaveFallDirection: - if (HaveFallData) - HaveFallDirection = data.ReadBit(); - break; - case MSEHaveTransportData: - HaveTransportData = data.ReadBit(); - break; - case MSETransportHaveTime2: - if (HaveTransportData) - HaveTransportTime2 = data.ReadBit(); - break; - case MSETransportHaveTime3: - if (HaveTransportData) - HaveTransportTime3 = data.ReadBit(); - break; - case MSEHaveSpline: - HaveSpline = data.ReadBit(); - break; - case MSEHaveSplineElev: - HaveSplineElevation = data.ReadBit(); - break; - case MSEPositionX: - data >> mi->pos.PositionXYZStream(); - break; - case MSEPositionY: - case MSEPositionZ: - break; // assume they always go as vector of 3 - case MSEPositionO: - data >> mi->pos.m_orientation; - break; - case MSEPitch: - if (HavePitch) - data >> mi->pitch; - break; - case MSEFallTime: - if (HaveFallData) - data >> mi->fallTime; - break; - case MSESplineElev: - if (HaveSplineElevation) - data >> mi->splineElevation; - break; - case MSEFallHorizontalSpeed: - if (HaveFallDirection) - data >> mi->j_xyspeed; - break; - case MSEFallVerticalSpeed: - if (HaveFallData) - data >> mi->j_zspeed; - break; - case MSEFallCosAngle: - if (HaveFallDirection) - data >> mi->j_cosAngle; - break; - case MSEFallSinAngle: - if (HaveFallDirection) - data >> mi->j_sinAngle; - break; - case MSETransportSeat: - if (HaveTransportData) - data >> mi->t_seat; - break; - case MSETransportPositionO: - if (HaveTransportData) - data >> mi->t_pos.m_orientation; - break; - case MSETransportPositionX: - if (HaveTransportData) - data >> mi->t_pos.PositionXYZStream(); - break; - case MSETransportPositionY: - case MSETransportPositionZ: - break; // assume they always go as vector of 3 - case MSETransportTime: - if (HaveTransportData) - data >> mi->t_time; - break; - case MSETransportTime2: - if (HaveTransportTime2) - data >> mi->t_time2; - break; - case MSETransportTime3: - if (HaveTransportTime3) - data >> mi->t_time3; - break; - default: - WPError(false, "Incorrect sequence element detected at ReadMovementInfo"); - } - } - - mi->guid = guid.guid; - mi->t_guid = tguid.guid; - - if (HaveTransportData && mi->pos.m_positionX != mi->t_pos.m_positionX) - if (GetPlayer()->GetTransport()) - GetPlayer()->GetTransport()->UpdatePosition(mi); -} - -void WorldSession::WriteMovementInfo(WorldPacket &data, MovementInfo* mi) -{ - bool HaveTransportData = mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT), - HaveTransportTime2 = (mi->flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT) != 0, - HaveTransportTime3 = false, - HavePitch = (mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING))) - || (mi->flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING), - HaveFallData = mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_TURNING), - HaveFallDirection = mi->HasMovementFlag(MOVEMENTFLAG_JUMPING), - HaveSplineElevation = mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION), - HaveSpline = false; - - MovementStatusElements *sequence = GetMovementStatusElementsSequence(data.GetOpcode()); - if(!sequence) - return; - uint8 *guid = (uint8 *)&mi->guid; - uint8 *tguid = (uint8 *)&mi->t_guid; - for(uint32 i=0; i < MSE_COUNT; i++) - { - MovementStatusElements element = sequence[i]; - - if (element >= MSEGuidByte0 && element <= MSEGuidByte7) - { - data.WriteByteMask(guid[element - MSEGuidByte0]); - continue; - } - - if (element >= MSETransportGuidByte0 && - element <= MSETransportGuidByte7) - { - if (HaveTransportData) - data.WriteByteMask(tguid[element - MSETransportGuidByte0]); - continue; - } - - if (element >= MSEGuidByte0_2 && element <= MSEGuidByte7_2) - { - data.WriteByteSeq(guid[element - MSEGuidByte0_2]); - continue; - } - - if (element >= MSETransportGuidByte0_2 && - element <= MSETransportGuidByte7_2) - { - if (HaveTransportData) - data.WriteByteSeq(tguid[element - MSETransportGuidByte0_2]); - continue; - } - - switch (element) - { - case MSEFlags: - data.WriteBits(mi->flags, 30); - break; - case MSEFlags2: - data.WriteBits(mi->flags2, 12); - break; - case MSETimestamp: - data << mi->time; - break; - case MSEHavePitch: - data.WriteBit(HavePitch); - break; - case MSEHaveFallData: - data.WriteBit(HaveFallData); - break; - case MSEHaveFallDirection: - if (HaveFallData) - data.WriteBit(HaveFallDirection); - break; - case MSEHaveTransportData: - data.WriteBit(HaveTransportData); - break; - case MSETransportHaveTime2: - if (HaveTransportData) - data.WriteBit(HaveTransportTime2); - break; - case MSETransportHaveTime3: - if (HaveTransportData) - data.WriteBit(HaveTransportTime3); - break; - case MSEHaveSpline: - data.WriteBit(HaveSpline); - break; - case MSEHaveSplineElev: - data.WriteBit(HaveSplineElevation); - break; - case MSEPositionX: - data << mi->pos.PositionXYZStream(); - break; - case MSEPositionY: - case MSEPositionZ: - break; // assume they always go as vector of 3 - case MSEPositionO: - data << mi->pos.m_orientation; - break; - case MSEPitch: - if (HavePitch) - data << mi->pitch; - break; - case MSEFallTime: - if (HaveFallData) - data << mi->fallTime; - break; - case MSESplineElev: - if (HaveSplineElevation) - data << mi->splineElevation; - break; - case MSEFallHorizontalSpeed: - if (HaveFallDirection) - data << mi->j_xyspeed; - break; - case MSEFallVerticalSpeed: - if (HaveFallData) - data << mi->j_zspeed; - break; - case MSEFallCosAngle: - if (HaveFallDirection) - data << mi->j_cosAngle; - break; - case MSEFallSinAngle: - if (HaveFallDirection) - data << mi->j_sinAngle; - break; - case MSETransportSeat: - if (HaveTransportData) - data << mi->t_seat; - break; - case MSETransportPositionO: - if (HaveTransportData) - data << mi->t_pos.m_orientation; - break; - case MSETransportPositionX: - if (HaveTransportData) - data << mi->t_pos.PositionXYZStream(); - break; - case MSETransportPositionY: - case MSETransportPositionZ: - break; // assume they always go as vector of 3 - case MSETransportTime: - if (HaveTransportData) - data << mi->t_time; - break; - case MSETransportTime2: - if (HaveTransportTime2) - data << mi->t_time2; - break; - case MSETransportTime3: - if (HaveTransportTime3) - data << mi->t_time3; - break; - default: - WPError(false, "Incorrect sequence element detected at ReadMovementInfo"); - } - } -} diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp deleted file mode 100755 index c1b59b41ebb..00000000000 --- a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp +++ /dev/null @@ -1,915 +0,0 @@ -/* - * 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 "Language.h" -#include "DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Player.h" -#include "GossipDef.h" -#include "UpdateMask.h" -#include "ObjectAccessor.h" -#include "Creature.h" -#include "Pet.h" -#include "BattlegroundMgr.h" -#include "Battleground.h" -#include "ScriptMgr.h" -#include "CreatureAI.h" -#include "SpellInfo.h" - -enum StableResultCode -{ - STABLE_ERR_MONEY = 0x01, // "you don't have enough money" - STABLE_ERR_STABLE = 0x06, // currently used in most fail cases - STABLE_SUCCESS_STABLE = 0x08, // stable success - STABLE_SUCCESS_UNSTABLE = 0x09, // unstable/swap success - STABLE_SUCCESS_BUY_SLOT = 0x0A, // buy slot success - STABLE_ERR_EXOTIC = 0x0C, // "you are unable to control exotic creatures" -}; - -void WorldSession::HandleTabardVendorActivateOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TABARDDESIGNER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendTabardVendorActivate(guid); -} - -void WorldSession::SendTabardVendorActivate(uint64 guid) -{ - WorldPacket data(MSG_TABARDVENDOR_ACTIVATE, 8); - data << guid; - SendPacket(&data); -} - -void WorldSession::HandleBankerActivateOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_BANKER_ACTIVATE"); - - recv_data >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendShowBank(guid); -} - -void WorldSession::SendShowBank(uint64 guid) -{ - WorldPacket data(SMSG_SHOW_BANK, 8); - data << guid; - SendPacket(&data); -} - -void WorldSession::HandleTrainerListOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - SendTrainerList(guid); -} - -void WorldSession::SendTrainerList(uint64 guid) -{ - std::string str = GetTrinityString(LANG_NPC_TAINER_HELLO); - SendTrainerList(guid, str); -} - -void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList"); - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // trainer list loaded at check; - if (!unit->isCanTrainingOf(_player, true)) - return; - - CreatureTemplate const* ci = unit->GetCreatureInfo(); - - if (!ci) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid)); - return; - } - - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", - GUID_LOPART(guid), unit->GetEntry()); - return; - } - - WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); - data << guid; - data << uint32(trainer_spells->trainerType); - data << uint32(0); - - size_t count_pos = data.wpos(); - data << uint32(trainer_spells->spellList.size()); - - // reputation discount - float fDiscountMod = _player->GetReputationPriceDiscount(unit); - bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; - - uint32 count = 0; - for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) - { - TrainerSpell const* tSpell = &itr->second; - - bool valid = true; - bool primary_prof_first_rank = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS ; ++i) - { - if (!tSpell->learnedSpell[i]) - continue; - if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i])) - { - valid = false; - break; - } - SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(tSpell->learnedSpell[i]); - if (learnedSpellInfo && learnedSpellInfo->IsPrimaryProfessionFirstRank()) - primary_prof_first_rank = true; - } - if (!valid) - continue; - - TrainerSpellState state = _player->GetTrainerSpellState(tSpell); - - data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) - data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); - data << uint32(floor(tSpell->spellCost * fDiscountMod)); - - data << uint8(tSpell->reqLevel); - data << uint32(tSpell->reqSkill); - data << uint32(tSpell->reqSkillValue); - //prev + req or req + 0 - uint8 maxReq = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS ; ++i) - { - if (!tSpell->learnedSpell[i]) - continue; - if (uint32 prevSpellId = sSpellMgr->GetPrevSpellInChain(tSpell->learnedSpell[i])) - { - data << uint32(prevSpellId); - ++maxReq; - } - if (maxReq == 2) - break; - SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]); - for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) - { - data << uint32(itr2->second); - ++maxReq; - } - if (maxReq == 2) - break; - } - while (maxReq < 2) - { - data << uint32(0); - ++maxReq; - } - - data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); - // primary prof. learn confirmation dialog - data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state - - ++count; - } - - data << strTitle; - - data.put<uint32>(count_pos, count); - SendPacket(&data); -} - -void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 spellId = 0; - int32 unkInt; - - recv_data >> guid >> unkInt >> spellId; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u", uint32(GUID_LOPART(guid)), spellId); - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (!unit->isCanTrainingOf(_player, true)) - return; - - // check present spell in trainer spell list - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) - return; - - // not found, cheat? - TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); - if (!trainer_spell) - return; - - // can't be learn, cheat? Or double learn with lags... - if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) - return; - - // apply reputation discount - uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); - - // check money requirement - if (!_player->HasEnoughMoney(nSpellCost)) - return; - - _player->ModifyMoney(-int32(nSpellCost)); - - unit->SendPlaySpellVisual(179); // 53 SpellCastDirected - unit->SendPlaySpellImpact(_player->GetGUID(), 362); // 113 EmoteSalute - - // learn explicitly or cast explicitly - if (trainer_spell->IsCastable()) - _player->CastSpell(_player, trainer_spell->spell, true); - else - _player->learnSpell(spellId, false); - - WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12); - data << uint64(guid); - data << uint32(spellId); // should be same as in packet from client - data << uint32(0); // "Trainer service", 1 = "Not enough money for trainer service <TS>". 0 = "Trainer service <TS> unavailable" - SendPacket(&data); -} - -void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GOSSIP_HELLO"); - - uint64 guid; - recv_data >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // set faction visible if needed - if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) - _player->GetReputationMgr().SetVisible(factionTemplateEntry); - - GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - // remove fake death - //if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider() || unit->isGuard()) - { - unit->StopMoving(); - } - - // If spiritguide, no need for gossip menu, just put player into resurrect queue - if (unit->isSpiritGuide()) - { - Battleground* bg = _player->GetBattleground(); - if (bg) - { - bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID()); - sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID()); - return; - } - } - - if (!sScriptMgr->OnGossipHello(_player, unit)) - { -// _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID()); - _player->PrepareGossipMenu(unit, unit->GetCreatureInfo()->GossipMenuId, true); - _player->SendPreparedGossip(unit); - } - unit->AI()->sGossipHello(_player); -} - -/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_GOSSIP_SELECT_OPTION"); - - uint32 option; - uint32 unk; - uint64 guid; - std::string code = ""; - - recv_data >> guid >> unk >> option; - - if (_player->PlayerTalkClass->GossipOptionCoded(option)) - { - sLog->outDebug(LOG_FILTER_PACKETIO, "reading string"); - recv_data >> code; - sLog->outDebug(LOG_FILTER_PACKETIO, "string read: %s", code.c_str()); - } - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) - { - sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (!code.empty()) - { - if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str())) - unit->OnGossipSelect (_player, option); - } - else - { - if (!Script->OnGossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) - unit->OnGossipSelect (_player, option); - } -}*/ - -void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); - - uint64 guid; - - recv_data >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendSpiritResurrect(); -} - -void WorldSession::SendSpiritResurrect() -{ - _player->ResurrectPlayer(0.5f, true); - - _player->DurabilityLossAll(0.25f, true); - - // get corpse nearest graveyard - WorldSafeLocsEntry const* corpseGrave = NULL; - Corpse* corpse = _player->GetCorpse(); - if (corpse) - corpseGrave = sObjectMgr->GetClosestGraveYard( - corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam()); - - // now can spawn bones - _player->SpawnCorpseBones(); - - // teleport to nearest from corpse graveyard, if different from nearest to player ghost - if (corpseGrave) - { - WorldSafeLocsEntry const* ghostGrave = sObjectMgr->GetClosestGraveYard( - _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam()); - - if (corpseGrave != ghostGrave) - _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); - // or update at original position - else - _player->UpdateObjectVisibility(); - } - // or update at original position - else - _player->UpdateObjectVisibility(); -} - -void WorldSession::HandleBinderActivateOpcode(WorldPacket & recv_data) -{ - uint64 npcGUID; - recv_data >> npcGUID; - - if (!GetPlayer()->IsInWorld() || !GetPlayer()->isAlive()) - return; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_INNKEEPER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendBindPoint(unit); -} - -void WorldSession::SendBindPoint(Creature* npc) -{ - // prevent set homebind to instances in any case - if (GetPlayer()->GetMap()->Instanceable()) - return; - - uint32 bindspell = 3286; - - // update sql homebind - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_HOMEBIND); - stmt->setUInt16(0, _player->GetMapId()); - stmt->setUInt16(1, _player->GetAreaId()); - stmt->setFloat (2, _player->GetPositionX()); - stmt->setFloat (3, _player->GetPositionY()); - stmt->setFloat (4, _player->GetPositionZ()); - stmt->setUInt32(5, _player->GetGUIDLow()); - CharacterDatabase.Execute(stmt); - - _player->m_homebindMapId = _player->GetMapId(); - _player->m_homebindAreaId = _player->GetAreaId(); - _player->m_homebindX = _player->GetPositionX(); - _player->m_homebindY = _player->GetPositionY(); - _player->m_homebindZ = _player->GetPositionZ(); - - // send spell for homebinding (3286) - npc->CastSpell(_player, bindspell, true); - - WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); - data << uint64(npc->GetGUID()); - data << uint32(bindspell); - data << uint32(0); // "Trainer service", 1 = "Not enough money for trainer service <TS>". 0 = "Trainer service <TS> unavailable" - SendPacket(&data); - - _player->PlayerTalkClass->SendCloseGossip(); -} - -void WorldSession::HandleListStabledPetsOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv MSG_LIST_STABLED_PETS"); - uint64 npcGUID; - - recv_data >> npcGUID; - - if (!CheckStableMaster(npcGUID)) - return; - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // remove mounts this fix bug where getting pet from stable while mounted deletes pet. - if (GetPlayer()->IsMounted()) - GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); - - SendStablePet(npcGUID); -} - -void WorldSession::SendStablePet(uint64 guid) -{ - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS_DETAIL); - - stmt->setUInt32(0, _player->GetGUIDLow()); - stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT); - stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT); - - _sendStabledPetCallback.SetParam(guid); - _sendStabledPetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); -} - -void WorldSession::SendStablePetCallback(PreparedQueryResult result, uint64 guid) -{ - if (!GetPlayer()) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv MSG_LIST_STABLED_PETS Send."); - - WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size - - data << uint64 (guid); - - Pet* pet = _player->GetPet(); - - size_t wpos = data.wpos(); - data << uint8(0); // place holder for slot show number - - data << uint8(GetPlayer()->m_stableSlots); - - uint8 num = 0; // counter for place holder - - // not let move dead pet in slot - if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET) - { - data << uint32(0); // 4.x unknown, some kind of order? - data << uint32(pet->GetCharmInfo()->GetPetNumber()); - data << uint32(pet->GetEntry()); - data << uint32(pet->getLevel()); - data << pet->GetName(); // petname - data << uint8(1); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show) - ++num; - } - - if (result) - { - do - { - Field* fields = result->Fetch(); - - data << uint32(fields[1].GetUInt32()); // petnumber - data << uint32(fields[2].GetUInt32()); // creature entry - data << uint32(fields[3].GetUInt16()); // level - data << fields[4].GetString(); // name - data << uint8(2); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show) - - ++num; - } - while (result->NextRow()); - } - - data.put<uint8>(wpos, num); // set real data to placeholder - SendPacket(&data); - -} - -void WorldSession::SendStableResult(uint8 res) -{ - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(res); - SendPacket(&data); -} - -void WorldSession::HandleStablePet(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_STABLE_PET"); - uint64 npcGUID; - - recv_data >> npcGUID; - - if (!GetPlayer()->isAlive()) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - if (!CheckStableMaster(npcGUID)) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Pet* pet = _player->GetPet(); - - // can't place in stable dead pet - if (!pet||!pet->isAlive()||pet->getPetType() != HUNTER_PET) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS); - - stmt->setUInt32(0, _player->GetGUIDLow()); - stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT); - stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT); - - _stablePetCallback = CharacterDatabase.AsyncQuery(stmt); -} - -void WorldSession::HandleStablePetCallback(PreparedQueryResult result) -{ - if (!GetPlayer()) - return; - - uint8 freeSlot = 1; - if (result) - { - do - { - Field* fields = result->Fetch(); - - uint8 slot = fields[1].GetUInt8(); - - // slots ordered in query, and if not equal then free - if (slot != freeSlot) - break; - - // this slot not free, skip - ++freeSlot; - } - while (result->NextRow()); - } - - WorldPacket data(SMSG_STABLE_RESULT, 1); - if (freeSlot > 0 && freeSlot <= GetPlayer()->m_stableSlots) - { - _player->RemovePet(_player->GetPet(), PetSaveMode(freeSlot)); - SendStableResult(STABLE_SUCCESS_STABLE); - } - else - SendStableResult(STABLE_ERR_STABLE); -} - -void WorldSession::HandleUnstablePet(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_UNSTABLE_PET."); - uint64 npcGUID; - uint32 petnumber; - - recv_data >> npcGUID >> petnumber; - - if (!CheckStableMaster(npcGUID)) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_ENTRY); - - stmt->setUInt32(0, _player->GetGUIDLow()); - stmt->setUInt32(1, petnumber); - stmt->setUInt8(2, PET_SAVE_FIRST_STABLE_SLOT); - stmt->setUInt8(3, PET_SAVE_LAST_STABLE_SLOT); - - _unstablePetCallback.SetParam(petnumber); - _unstablePetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); -} - -void WorldSession::HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId) -{ - if (!GetPlayer()) - return; - - uint32 petEntry = 0; - if (result) - { - Field* fields = result->Fetch(); - petEntry = fields[0].GetUInt32(); - } - - if (!petEntry) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry); - if (!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) - { - // if problem in exotic pet - if (creatureInfo && creatureInfo->isTameable(true)) - SendStableResult(STABLE_ERR_EXOTIC); - else - SendStableResult(STABLE_ERR_STABLE); - return; - } - - Pet* pet = _player->GetPet(); - if (pet && pet->isAlive()) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // delete dead pet - if (pet) - _player->RemovePet(pet, PET_SAVE_AS_DELETED); - - Pet* newPet = new Pet(_player, HUNTER_PET); - if (!newPet->LoadPetFromDB(_player, petEntry, petId)) - { - delete newPet; - newPet = NULL; - SendStableResult(STABLE_ERR_STABLE); - return; - } - - SendStableResult(STABLE_SUCCESS_UNSTABLE); -} - -void WorldSession::HandleBuyStableSlot(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_BUY_STABLE_SLOT."); - uint64 npcGUID; - - recv_data >> npcGUID; - - if (!CheckStableMaster(npcGUID)) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (GetPlayer()->m_stableSlots < MAX_PET_STABLES) - { - /*StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); - if (_player->HasEnoughMoney(SlotPrice->Price)) - { - ++GetPlayer()->m_stableSlots; - _player->ModifyMoney(-int32(SlotPrice->Price)); - SendStableResult(STABLE_SUCCESS_BUY_SLOT); - } - else - SendStableResult(STABLE_ERR_MONEY);*/ - } - else - SendStableResult(STABLE_ERR_STABLE); -} - -void WorldSession::HandleStableRevivePet(WorldPacket &/* recv_data */) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "HandleStableRevivePet: Not implemented"); -} - -void WorldSession::HandleStableSwapPet(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_STABLE_SWAP_PET."); - uint64 npcGUID; - uint32 petId; - - recv_data >> npcGUID >> petId; - - if (!CheckStableMaster(npcGUID)) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Pet* pet = _player->GetPet(); - - if (!pet || pet->getPetType() != HUNTER_PET) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // Find swapped pet slot in stable - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOT_BY_ID); - - stmt->setUInt32(0, _player->GetGUIDLow()); - stmt->setUInt32(1, petId); - - _stableSwapCallback.SetParam(petId); - _stableSwapCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); -} - -void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId) -{ - if (!GetPlayer()) - return; - - if (!result) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - Field* fields = result->Fetch(); - - uint32 slot = fields[0].GetUInt8(); - uint32 petEntry = fields[1].GetUInt32(); - - if (!petEntry) - { - SendStableResult(STABLE_ERR_STABLE); - return; - } - - CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry); - if (!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) - { - // if problem in exotic pet - if (creatureInfo && creatureInfo->isTameable(true)) - SendStableResult(STABLE_ERR_EXOTIC); - else - SendStableResult(STABLE_ERR_STABLE); - return; - } - - // move alive pet to slot or delete dead pet - Pet* pet = _player->GetPet(); - - _player->RemovePet(pet, pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED); - - // summon unstabled pet - Pet* newpet = new Pet(_player); - if (!newpet->LoadPetFromDB(_player, petEntry, petId)) - { - delete newpet; - SendStableResult(STABLE_ERR_STABLE); - } - else - SendStableResult(STABLE_SUCCESS_UNSTABLE); -} - -void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_REPAIR_ITEM"); - - uint64 npcGUID, itemGUID; - uint8 guildBank; // new in 2.3.2, bool that means from guild bank money - - recv_data >> npcGUID >> itemGUID >> guildBank; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_REPAIR); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // reputation discount - float discountMod = _player->GetReputationPriceDiscount(unit); - - if (itemGUID) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID)); - - Item* item = _player->GetItemByGuid(itemGUID); - if (item) - _player->DurabilityRepair(item->GetPos(), true, discountMod, guildBank); - } - else - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID)); - _player->DurabilityRepairAll(true, discountMod, guildBank); - } -} - diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.h b/src/server/game/Server/Protocol/Handlers/NPCHandler.h deleted file mode 100755 index af84b71a74f..00000000000 --- a/src/server/game/Server/Protocol/Handlers/NPCHandler.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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/>. - */ - -#ifndef __NPCHANDLER_H -#define __NPCHANDLER_H - -struct QEmote -{ - uint32 _Emote; - uint32 _Delay; -}; - -#define MAX_GOSSIP_TEXT_EMOTES 3 - -struct GossipTextOption -{ - std::string Text_0; - std::string Text_1; - uint32 Language; - float Probability; - QEmote Emotes[MAX_GOSSIP_TEXT_EMOTES]; -}; - -#define MAX_GOSSIP_TEXT_OPTIONS 8 - -struct GossipText -{ - GossipTextOption Options[MAX_GOSSIP_TEXT_OPTIONS]; -}; - -struct PageTextLocale -{ - StringVector Text; -}; - -struct NpcTextLocale -{ - NpcTextLocale() { Text_0.resize(8); Text_1.resize(8); } - - std::vector<StringVector> Text_0; - std::vector<StringVector> Text_1; -}; -#endif - diff --git a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp deleted file mode 100755 index 90cda17d477..00000000000 --- a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp +++ /dev/null @@ -1,875 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Spell.h" -#include "ObjectAccessor.h" -#include "CreatureAI.h" -#include "Util.h" -#include "Pet.h" -#include "World.h" -#include "Group.h" -#include "SpellInfo.h" - -void WorldSession::HandleDismissCritter(WorldPacket &recv_data) -{ - uint64 guid; - recv_data >> guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_DISMISS_CRITTER for GUID " UI64FMTD, guid); - - Unit* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!pet) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "Vanitypet (guid: %u) does not exist - player '%s' (guid: %u / account: %u) attempted to dismiss it (possibly lagged out)", - uint32(GUID_LOPART(guid)), GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetAccountId()); - return; - } - - if (_player->GetCritterGUID() == pet->GetGUID()) - { - if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isSummon()) - pet->ToTempSummon()->UnSummon(); - } -} - -void WorldSession::HandlePetAction(WorldPacket & recv_data) -{ - uint64 guid1; - uint32 data; - uint64 guid2; - float x, y, z; - recv_data >> guid1; //pet guid - recv_data >> data; - recv_data >> guid2; //tag guid - // Position - recv_data >> x; - recv_data >> y; - recv_data >> z; - - uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); - uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); //delete = 0x07 CastSpell = C1 - - // used also for charmed creature - Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); - sLog->outDetail("HandlePetAction: Pet %u - flag: %u, spellid: %u, target: %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2))); - - if (!pet) - { - sLog->outError("HandlePetAction: Pet (GUID: %u) doesn't exist for player '%s'", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName()); - return; - } - - if (pet != GetPlayer()->GetFirstControlled()) - { - sLog->outError("HandlePetAction: Pet (GUID: %u) does not belong to player '%s'", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName()); - return; - } - - if (!pet->isAlive()) - { - SpellInfo const* spell = (flag == ACT_ENABLED || flag == ACT_PASSIVE) ? sSpellMgr->GetSpellInfo(spellid) : NULL; - if (!spell) - return; - if (!(spell->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD)) - return; - } - - //TODO: allow control charmed player? - if (pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) - return; - - if (GetPlayer()->m_Controlled.size() == 1) - HandlePetActionHelper(pet, guid1, spellid, flag, guid2); - else - { - //If a pet is dismissed, m_Controlled will change - std::vector<Unit*> controlled; - for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) - if ((*itr)->GetEntry() == pet->GetEntry() && (*itr)->isAlive()) - controlled.push_back(*itr); - for (std::vector<Unit*>::iterator itr = controlled.begin(); itr != controlled.end(); ++itr) - HandlePetActionHelper(*itr, guid1, spellid, flag, guid2); - } -} - -void WorldSession::HandlePetStopAttack(WorldPacket &recv_data) -{ - uint64 guid; - recv_data >> guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PET_STOP_ATTACK for GUID " UI64FMTD "", guid); - - Unit* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!pet) - { - sLog->outError("HandlePetStopAttack: Pet %u does not exist", uint32(GUID_LOPART(guid))); - return; - } - - if (pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) - { - sLog->outError("HandlePetStopAttack: Pet GUID %u isn't a pet or charmed creature of player %s", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); - return; - } - - if (!pet->isAlive()) - return; - - pet->AttackStop(); -} - -void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid, uint16 flag, uint64 guid2) -{ - CharmInfo* charmInfo = pet->GetCharmInfo(); - if (!charmInfo) - { - sLog->outError("WorldSession::HandlePetAction(petGuid: " UI64FMTD ", tagGuid: " UI64FMTD ", spellId: %u, flag: %u): object (entry: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", - guid1, guid2, spellid, flag, pet->GetGUIDLow(), pet->GetTypeId()); - return; - } - - switch (flag) - { - case ACT_COMMAND: //0x07 - switch (spellid) - { - case COMMAND_STAY: //flat=1792 //STAY - pet->AttackStop(); - pet->InterruptNonMeleeSpells(false); - pet->GetMotionMaster()->MoveIdle(); - charmInfo->SetCommandState(COMMAND_STAY); - - charmInfo->SetIsCommandAttack(false); - charmInfo->SetIsAtStay(true); - charmInfo->SetIsFollowing(false); - charmInfo->SetIsReturning(false); - charmInfo->SaveStayPosition(); - break; - case COMMAND_FOLLOW: //spellid=1792 //FOLLOW - pet->AttackStop(); - pet->InterruptNonMeleeSpells(false); - pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle()); - charmInfo->SetCommandState(COMMAND_FOLLOW); - - charmInfo->SetIsCommandAttack(false); - charmInfo->SetIsAtStay(false); - charmInfo->SetIsReturning(true); - charmInfo->SetIsFollowing(false); - break; - case COMMAND_ATTACK: //spellid=1792 //ATTACK - { - // Can't attack if owner is pacified - if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY)) - { - //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED); - //TODO: Send proper error message to client - return; - } - - // only place where pet can be player - Unit* TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); - if (!TargetUnit) - return; - - if (Unit* owner = pet->GetOwner()) - if (!owner->IsValidAttackTarget(TargetUnit)) - return; - - // Not let attack through obstructions - if (sWorld->getBoolConfig(CONFIG_PET_LOS)) - { - if (!pet->IsWithinLOSInMap(TargetUnit)) - return; - } - - pet->ClearUnitState(UNIT_STAT_FOLLOW); - // This is true if pet has no target or has target but targets differs. - if (pet->getVictim() != TargetUnit || (pet->getVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) - { - if (pet->getVictim()) - pet->AttackStop(); - - if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled) - { - charmInfo->SetIsCommandAttack(true); - charmInfo->SetIsAtStay(false); - charmInfo->SetIsFollowing(false); - charmInfo->SetIsReturning(false); - - pet->ToCreature()->AI()->AttackStart(TargetUnit); - - //10% chance to play special pet attack talk, else growl - if (pet->ToCreature()->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); - else - { - // 90% chance for pet and 100% chance for charmed creature - pet->SendPetAIReaction(guid1); - } - } - else // charmed player - { - if (pet->getVictim() && pet->getVictim() != TargetUnit) - pet->AttackStop(); - - charmInfo->SetIsCommandAttack(true); - charmInfo->SetIsAtStay(false); - charmInfo->SetIsFollowing(false); - charmInfo->SetIsReturning(false); - - pet->Attack(TargetUnit, true); - pet->SendPetAIReaction(guid1); - } - } - break; - } - case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) - if (pet->GetCharmerGUID() == GetPlayer()->GetGUID()) - _player->StopCastingCharm(); - else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID()) - { - ASSERT(pet->GetTypeId() == TYPEID_UNIT); - if (pet->isPet()) - { - if (((Pet*)pet)->getPetType() == HUNTER_PET) - GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); - else - //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) - pet->setDeathState(CORPSE); - } - else if (pet->HasUnitTypeMask(UNIT_MASK_MINION)) - { - ((Minion*)pet)->UnSummon(); - } - } - break; - default: - sLog->outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); - } - break; - case ACT_REACTION: // 0x6 - switch (spellid) - { - case REACT_PASSIVE: //passive - pet->AttackStop(); - - case REACT_DEFENSIVE: //recovery - case REACT_AGGRESSIVE: //activete - if (pet->GetTypeId() == TYPEID_UNIT) - pet->ToCreature()->SetReactState(ReactStates(spellid)); - break; - } - break; - case ACT_DISABLED: // 0x81 spell (disabled), ignore - case ACT_PASSIVE: // 0x01 - case ACT_ENABLED: // 0xC1 spell - { - Unit* unit_target = NULL; - - if (guid2) - unit_target = ObjectAccessor::GetUnit(*_player, guid2); - - // do not cast unknown spells - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); - if (!spellInfo) - { - sLog->outError("WORLD: unknown PET spell id %i", spellid); - return; - } - - if (spellInfo->StartRecoveryCategory > 0) - if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) - return; - - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) - return; - } - - // do not cast not learned spells - if (!pet->HasSpell(spellid) || spellInfo->IsPassive()) - return; - - // Clear the flags as if owner clicked 'attack'. AI will reset them - // after AttackStart, even if spell failed - if (pet->GetCharmInfo()) - { - pet->GetCharmInfo()->SetIsAtStay(false); - pet->GetCharmInfo()->SetIsCommandAttack(true); - pet->GetCharmInfo()->SetIsReturning(false); - pet->GetCharmInfo()->SetIsFollowing(false); - } - - Spell* spell = new Spell(pet, spellInfo, TRIGGERED_NONE); - - SpellCastResult result = spell->CheckPetCast(unit_target); - - //auto turn to target unless possessed - if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed() && !pet->IsVehicle()) - { - if (unit_target) - { - pet->SetInFront(unit_target); - if (unit_target->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer((Player*)unit_target); - } - else if (Unit* unit_target2 = spell->m_targets.GetUnitTarget()) - { - pet->SetInFront(unit_target2); - if (unit_target2->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer((Player*)unit_target2); - } - if (Unit* powner = pet->GetCharmerOrOwner()) - if (powner->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer(powner->ToPlayer()); - result = SPELL_CAST_OK; - } - - if (result == SPELL_CAST_OK) - { - pet->ToCreature()->AddCreatureSpellCooldown(spellid); - - unit_target = spell->m_targets.GetUnitTarget(); - - //10% chance to play special pet attack talk, else growl - //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->ToCreature()->isPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); - else - { - pet->SendPetAIReaction(guid1); - } - - if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed() && !pet->IsVehicle()) - { - // This is true if pet has no target or has target but targets differs. - if (pet->getVictim() != unit_target) - { - if (pet->getVictim()) - pet->AttackStop(); - pet->GetMotionMaster()->Clear(); - if (pet->ToCreature()->IsAIEnabled) - pet->ToCreature()->AI()->AttackStart(unit_target); - } - } - - spell->prepare(&(spell->m_targets)); - } - else - { - if (pet->isPossessed() || pet->IsVehicle()) - Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); - else - pet->SendPetCastFail(spellid, result); - - if (!pet->ToCreature()->HasSpellCooldown(spellid)) - GetPlayer()->SendClearCooldown(spellid, pet); - - spell->finish(false); - delete spell; - - // reset specific flags in case of spell fail. AI will reset other flags - if (pet->GetCharmInfo()) - pet->GetCharmInfo()->SetIsCommandAttack(false); - } - break; - } - default: - sLog->outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); - } -} - -void WorldSession::HandlePetNameQuery(WorldPacket & recv_data) -{ - sLog->outDetail("HandlePetNameQuery. CMSG_PET_NAME_QUERY"); - - uint32 petnumber; - uint64 petguid; - - recv_data >> petnumber; - recv_data >> petguid; - - SendPetNameQuery(petguid, petnumber); -} - -void WorldSession::SendPetNameQuery(uint64 petguid, uint32 petnumber) -{ - Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); - if (!pet) - { - WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+1+4+1)); - data << uint32(petnumber); - data << uint8(0); - data << uint32(0); - data << uint8(0); - _player->GetSession()->SendPacket(&data); - return; - } - - std::string name = pet->GetName(); - - WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); - data << uint32(petnumber); - data << name.c_str(); - data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); - - if (pet->isPet() && ((Pet*)pet)->GetDeclinedNames()) - { - data << uint8(1); - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << ((Pet*)pet)->GetDeclinedNames()->name[i]; - } - else - data << uint8(0); - - _player->GetSession()->SendPacket(&data); -} - -bool WorldSession::CheckStableMaster(uint64 guid) -{ - // spell case or GM - if (guid == GetPlayer()->GetGUID()) - { - if (!GetPlayer()->isGameMaster() && !GetPlayer()->HasAuraType(SPELL_AURA_OPEN_STABLE)) - { - sLog->outStaticDebug("Player (GUID:%u) attempt open stable in cheating way.", GUID_LOPART(guid)); - return false; - } - } - // stable master case - else - { - if (!GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_STABLEMASTER)) - { - sLog->outStaticDebug("Stablemaster (GUID:%u) not found or you can't interact with him.", GUID_LOPART(guid)); - return false; - } - } - return true; -} - -void WorldSession::HandlePetSetAction(WorldPacket & recv_data) -{ - sLog->outDetail("HandlePetSetAction. CMSG_PET_SET_ACTION"); - - uint64 petguid; - uint8 count; - - recv_data >> petguid; - - Unit* pet = ObjectAccessor::GetUnit(*_player, petguid); - - if (!pet || pet != _player->GetFirstControlled()) - { - sLog->outError("HandlePetSetAction: Unknown pet (GUID: %u) or pet owner (GUID: %u)", GUID_LOPART(petguid), _player->GetGUIDLow()); - return; - } - - CharmInfo* charmInfo = pet->GetCharmInfo(); - if (!charmInfo) - { - sLog->outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); - return; - } - - count = (recv_data.size() == 24) ? 2 : 1; - - uint32 position[2]; - uint32 data[2]; - bool move_command = false; - - for (uint8 i = 0; i < count; ++i) - { - recv_data >> position[i]; - recv_data >> data[i]; - - uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); - - //ignore invalid position - if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX) - return; - - // in the normal case, command and reaction buttons can only be moved, not removed - // at moving count == 2, at removing count == 1 - // ignore attempt to remove command|reaction buttons (not possible at normal case) - if (act_state == ACT_COMMAND || act_state == ACT_REACTION) - { - if (count == 1) - return; - - move_command = true; - } - } - - // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) - if (move_command) - { - uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); - if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) - { - uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); - UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); - if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || - act_state_0 != actionEntry_1->GetType()) - return; - } - - uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); - if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) - { - uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); - UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); - if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || - act_state_1 != actionEntry_0->GetType()) - return; - } - } - - for (uint8 i = 0; i < count; ++i) - { - uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); - uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); - - sLog->outDetail("Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state)); - - //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add - if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) - { - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id)) - { - //sign for autocast - if (act_state == ACT_ENABLED) - { - if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) - ((Pet*)pet)->ToggleAutocast(spellInfo, true); - else - for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) - if ((*itr)->GetEntry() == pet->GetEntry()) - (*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, true); - } - //sign for no/turn off autocast - else if (act_state == ACT_DISABLED) - { - if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) - ((Pet*)pet)->ToggleAutocast(spellInfo, false); - else - for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) - if ((*itr)->GetEntry() == pet->GetEntry()) - (*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, false); - } - } - - charmInfo->SetActionBar(position[i], spell_id, ActiveStates(act_state)); - } - } -} - -void WorldSession::HandlePetRename(WorldPacket & recv_data) -{ - sLog->outDetail("HandlePetRename. CMSG_PET_RENAME"); - - uint64 petguid; - uint8 isdeclined; - - std::string name; - DeclinedName declinedname; - - recv_data >> petguid; - recv_data >> name; - recv_data >> isdeclined; - - Pet* pet = ObjectAccessor::FindPet(petguid); - // check it! - if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || - !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || - pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) - return; - - PetNameInvalidReason res = ObjectMgr::CheckPetName(name); - if (res != PET_NAME_SUCCESS) - { - SendPetNameInvalid(res, name, NULL); - return; - } - - if (sObjectMgr->IsReservedName(name)) - { - SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); - return; - } - - pet->SetName(name); - - Unit* owner = pet->GetOwner(); - if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) - owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); - - pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); - - if (isdeclined) - { - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - { - recv_data >> declinedname.name[i]; - } - - std::wstring wname; - Utf8toWStr(name, wname); - if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) - { - SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); - return; - } - } - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - if (isdeclined) - { - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - CharacterDatabase.EscapeString(declinedname.name[i]); - trans->PAppend("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); - trans->PAppend("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u', '%u', '%s', '%s', '%s', '%s', '%s')", - pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); - } - - CharacterDatabase.EscapeString(name); - trans->PAppend("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); - CharacterDatabase.CommitTransaction(trans); - - pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped -} - -void WorldSession::HandlePetAbandon(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; //pet guid - sLog->outDetail("HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); - - if (!_player->IsInWorld()) - return; - - // pet/charmed - Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - if (pet) - { - if (pet->isPet()) - _player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); - else if (pet->GetGUID() == _player->GetCharmGUID()) - _player->StopCastingCharm(); - } -} - -void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) -{ - sLog->outDetail("CMSG_PET_SPELL_AUTOCAST"); - uint64 guid; - uint32 spellid; - uint8 state; //1 for on, 0 for off - recvPacket >> guid >> spellid >> state; - - if (!_player->GetGuardianPet() && !_player->GetCharm()) - return; - - if (ObjectAccessor::FindPlayer(guid)) - return; - - Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) - { - sLog->outError("HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); - return; - } - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); - // do not add not learned spells/ passive spells - if (!pet->HasSpell(spellid) || spellInfo->IsAutocastable()) - return; - - CharmInfo* charmInfo = pet->GetCharmInfo(); - if (!charmInfo) - { - sLog->outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); - return; - } - - if (pet->isPet()) - ((Pet*)pet)->ToggleAutocast(spellInfo, state); - else - pet->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, state); - - charmInfo->SetSpellAutocast(spellInfo, state); -} - -void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) -{ - sLog->outDetail("WORLD: CMSG_PET_CAST_SPELL"); - - uint64 guid; - uint8 castCount; - uint32 spellId; - uint8 castFlags; - - recvPacket >> guid >> castCount >> spellId >> castFlags; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_CAST_SPELL, guid: " UI64FMTD ", castCount: %u, spellId %u, castFlags %u", guid, castCount, spellId, castFlags); - - // This opcode is also sent from charmed and possessed units (players and creatures) - if (!_player->GetGuardianPet() && !_player->GetCharm()) - return; - - Unit* caster = ObjectAccessor::GetUnit(*_player, guid); - - if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) - { - sLog->outError("HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); - return; - } - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - sLog->outError("WORLD: unknown PET spell id %i", spellId); - return; - } - - if (spellInfo->StartRecoveryCategory > 0) // Check if spell is affected by GCD - if (caster->GetTypeId() == TYPEID_UNIT && caster->GetCharmInfo() && caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) - { - caster->SendPetCastFail(spellId, SPELL_FAILED_NOT_READY); - return; - } - - // do not cast not learned spells - if (!caster->HasSpell(spellId) || spellInfo->IsPassive()) - return; - - SpellCastTargets targets; - targets.Read(recvPacket, caster); - HandleClientCastFlags(recvPacket, castFlags, targets); - - caster->ClearUnitState(UNIT_STAT_FOLLOW); - - Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE); - spell->m_cast_count = castCount; // probably pending spell cast - spell->m_targets = targets; - - // TODO: need to check victim? - SpellCastResult result; - if (caster->m_movedPlayer) - result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit()); - else - result = spell->CheckPetCast(NULL); - if (result == SPELL_CAST_OK) - { - if (caster->GetTypeId() == TYPEID_UNIT) - { - Creature* pet = caster->ToCreature(); - pet->AddCreatureSpellCooldown(spellId); - if (pet->isPet()) - { - Pet* p = (Pet*)pet; - // 10% chance to play special pet attack talk, else growl - // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); - else - pet->SendPetAIReaction(guid); - } - } - - spell->prepare(&(spell->m_targets)); - } - else - { - caster->SendPetCastFail(spellId, result); - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (!caster->ToPlayer()->HasSpellCooldown(spellId)) - GetPlayer()->SendClearCooldown(spellId, caster); - } - else - { - if (!caster->ToCreature()->HasSpellCooldown(spellId)) - GetPlayer()->SendClearCooldown(spellId, caster); - } - - spell->finish(false); - delete spell; - } -} - -void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) -{ - WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1); - data << uint32(error); - data << name; - if (declinedName) - { - data << uint8(1); - for (uint32 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << declinedName->name[i]; - } - else - data << uint8(0); - SendPacket(&data); -} - -void WorldSession::HandlePetLearnTalent(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_LEARN_TALENT"); - - uint64 guid; - uint32 talentId, requestedRank; - recv_data >> guid >> talentId >> requestedRank; - - _player->LearnPetTalent(guid, talentId, requestedRank); - _player->SendTalentsInfoData(true); -} - -void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LEARN_PREVIEW_TALENTS_PET"); - - uint64 guid; - recv_data >> guid; - - uint32 talentsCount; - recv_data >> talentsCount; - - uint32 talentId, talentRank; - - for (uint32 i = 0; i < talentsCount; ++i) - { - recv_data >> talentId >> talentRank; - - _player->LearnPetTalent(guid, talentId, talentRank); - } - - _player->SendTalentsInfoData(true); -} diff --git a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp deleted file mode 100755 index dce5e0f78ba..00000000000 --- a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp +++ /dev/null @@ -1,937 +0,0 @@ -/* - * 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 "Language.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "ArenaTeamMgr.h" -#include "GuildMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Guild.h" -#include "ArenaTeam.h" -#include "GossipDef.h" -#include "SocialMgr.h" - -#define CHARTER_DISPLAY_ID 16161 - -/*enum PetitionType // dbc data -{ - PETITION_TYPE_GUILD = 1, - PETITION_TYPE_ARENA_TEAM = 3 -};*/ - -// Charters ID in item_template -enum CharterItemIDs -{ - GUILD_CHARTER = 5863, - ARENA_TEAM_CHARTER_2v2 = 23560, - ARENA_TEAM_CHARTER_3v3 = 23561, - ARENA_TEAM_CHARTER_5v5 = 23562 -}; - -enum CharterCosts -{ - GUILD_CHARTER_COST = 1000, - ARENA_TEAM_CHARTER_2v2_COST = 800000, - ARENA_TEAM_CHARTER_3v3_COST = 1200000, - ARENA_TEAM_CHARTER_5v5_COST = 2000000 -}; - -void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_BUY"); - - uint64 guidNPC; - uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client - std::string name; - - recv_data >> guidNPC; // NPC GUID - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint64>(); // 0 - recv_data >> name; // name - recv_data.read_skip<std::string>(); // some string - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint16>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - recv_data.read_skip<uint32>(); // 0 - - for (int i = 0; i < 10; ++i) - recv_data.read_skip<std::string>(); - - recv_data >> clientIndex; // index - recv_data.read_skip<uint32>(); // 0 - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); - - // prevent cheating - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC, UNIT_NPC_FLAG_PETITIONER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - uint32 charterid = 0; - uint32 cost = 0; - uint32 type = 0; - if (creature->isTabardDesigner()) - { - // if tabard designer, then trying to buy a guild charter. - // do not let if already in guild. - if (_player->GetGuildId()) - return; - - charterid = GUILD_CHARTER; - cost = GUILD_CHARTER_COST; - type = GUILD_CHARTER_TYPE; - } - else - { - // TODO: find correct opcode - if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); - return; - } - - switch (clientIndex) // arenaSlot+1 as received from client (1 from 3 case) - { - case 1: - charterid = ARENA_TEAM_CHARTER_2v2; - cost = ARENA_TEAM_CHARTER_2v2_COST; - type = ARENA_TEAM_CHARTER_2v2_TYPE; - break; - case 2: - charterid = ARENA_TEAM_CHARTER_3v3; - cost = ARENA_TEAM_CHARTER_3v3_COST; - type = ARENA_TEAM_CHARTER_3v3_TYPE; - break; - case 3: - charterid = ARENA_TEAM_CHARTER_5v5; - cost = ARENA_TEAM_CHARTER_5v5_COST; - type = ARENA_TEAM_CHARTER_5v5_TYPE; - break; - default: - sLog->outDebug(LOG_FILTER_NETWORKIO, "unknown selection at buy arena petition: %u", clientIndex); - return; - } - - if (_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - } - - if (type == GUILD_CHARTER_TYPE) - { - if (sGuildMgr->GetGuildByName(name)) - { - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name); - return; - } - if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) - { - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_INVALID, name); - return; - } - } - else - { - if (sArenaTeamMgr->GetArenaTeamByName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); - return; - } - if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - } - - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(charterid); - if (!pProto) - { - _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); - return; - } - - if (!_player->HasEnoughMoney(cost)) - { //player hasn't got enough money - _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, charterid, 0); - return; - } - - ItemPosCountVec dest; - InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, NULL, NULL, charterid); - return; - } - - _player->ModifyMoney(-(int32)cost); - Item* charter = _player->StoreNewItem(dest, charterid, true); - if (!charter) - return; - - charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); - // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id - // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) - charter->SetState(ITEM_CHANGED, _player); - _player->SendNewItem(charter, 1, true, false); - - // a petition is invalid, if both the owner and the type matches - // we checked above, if this player is in an arenateam, so this must be - // datacorruption - QueryResult result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type); - - std::ostringstream ssInvalidPetitionGUIDs; - - if (result) - { - do - { - Field* fields = result->Fetch(); - ssInvalidPetitionGUIDs << '\'' << fields[0].GetUInt32() << "', "; - } while (result->NextRow()); - } - - // delete petitions with the same guid as this one - ssInvalidPetitionGUIDs << '\'' << charter->GetGUIDLow() << '\''; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.EscapeString(name); - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - trans->PAppend("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - trans->PAppend("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", - _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type); - CharacterDatabase.CommitTransaction(trans); -} - -void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) -{ - // ok - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); - - uint8 signs = 0; - uint64 petitionguid; - recv_data >> petitionguid; // petition guid - - // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) - uint32 petitionguid_low = GUID_LOPART(petitionguid); - - QueryResult result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); - if (!result) - { - sLog->outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); - return; - } - Field* fields = result->Fetch(); - uint32 type = fields[0].GetUInt8(); - - // if guild petition and has guild => error, return; - if (type == GUILD_CHARTER_TYPE && _player->GetGuildId()) - return; - - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low); - - // result == NULL also correct in case no sign yet - if (result) - signs = uint8(result->GetRowCount()); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low); - - WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12)); - data << uint64(petitionguid); // petition guid - data << uint64(_player->GetGUID()); // owner guid - data << uint32(petitionguid_low); // guild guid - data << uint8(signs); // sign's count - - for (uint8 i = 1; i <= signs; ++i) - { - Field* fields2 = result->Fetch(); - uint64 plguid = fields2[0].GetUInt64(); - - data << uint64(plguid); // Player GUID - data << uint32(0); // there 0 ... - - result->NextRow(); - } - SendPacket(&data); -} - -void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_QUERY"); // ok - - uint32 guildguid; - uint64 petitionguid; - recv_data >> guildguid; // in Trinity always same as GUID_LOPART(petitionguid) - recv_data >> petitionguid; // petition guid - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid); - - SendPetitionQueryOpcode(petitionguid); -} - -void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) -{ - uint64 ownerguid = 0; - uint32 type; - std::string name = "NO_NAME_FOR_GUID"; - - // TODO: Use CHAR_LOAD_PETITION PS - QueryResult result = CharacterDatabase.PQuery("SELECT ownerguid, name, type " - "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - - if (result) - { - Field* fields = result->Fetch(); - ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - name = fields[1].GetString(); - type = fields[2].GetUInt32(); - } - else - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; - } - - WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10)); - data << uint32(GUID_LOPART(petitionguid)); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid) - data << uint64(ownerguid); // charter owner guid - data << name; // name (guild/arena team) - data << uint8(0); // some string - if (type == GUILD_CHARTER_TYPE) - { - data << uint32(9); - data << uint32(9); - data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition - } - else - { - data << uint32(type-1); - data << uint32(type-1); - data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition - } - data << uint32(0); // 5 - data << uint32(0); // 6 - data << uint32(0); // 7 - data << uint32(0); // 8 - data << uint16(0); // 9 2 bytes field - data << uint32(0); // 10 - data << uint32(0); // 11 - data << uint32(0); // 13 count of next strings? - - for (int i = 0; i < 10; ++i) - data << uint8(0); // some string - - data << uint32(0); // 14 - - if (type == GUILD_CHARTER_TYPE) - data << uint32(0); // 15 0 - guild, 1 - arena team - else - data << uint32(1); - - SendPacket(&data); -} - -void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_RENAME"); - - uint64 petitionGuid; - uint32 type; - std::string newName; - - recv_data >> petitionGuid; // guid - recv_data >> newName; // new name - - Item* item = _player->GetItemByGuid(petitionGuid); - if (!item) - return; - - QueryResult result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); - - if (result) - { - Field* fields = result->Fetch(); - type = fields[0].GetUInt8(); - } - else - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionGuid)); - return; - } - - if (type == GUILD_CHARTER_TYPE) - { - if (sGuildMgr->GetGuildByName(newName)) - { - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, newName); - return; - } - if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName)) - { - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_INVALID, newName); - return; - } - } - else - { - if (sArenaTeamMgr->GetArenaTeamByName(newName)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_EXISTS_S); - return; - } - if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); - - stmt->setString(0, newName); - stmt->setUInt32(1, GUID_LOPART(petitionGuid)); - - CharacterDatabase.Execute(stmt); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionGuid), newName.c_str()); - WorldPacket data(MSG_PETITION_RENAME, (8+newName.size()+1)); - data << uint64(petitionGuid); - data << newName; - SendPacket(&data); -} - -void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_SIGN"); // ok - - Field* fields; - uint64 petitionGuid; - uint8 unk; - recv_data >> petitionGuid; // petition guid - recv_data >> unk; - - QueryResult result = CharacterDatabase.PQuery( - "SELECT ownerguid, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " - " type " - "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid), GUID_LOPART(petitionGuid)); - - if (!result) - { - sLog->outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionGuid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); - return; - } - - fields = result->Fetch(); - uint64 ownerGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - uint8 signs = fields[1].GetUInt8(); - uint32 type = fields[2].GetUInt32(); - - uint32 playerGuid = _player->GetGUIDLow(); - if (GUID_LOPART(ownerGuid) == playerGuid) - return; - - // not let enemies sign guild charter - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr->GetPlayerTeamByGUID(ownerGuid)) - { - if (type != GUILD_CHARTER_TYPE) - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - else - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NOT_ALLIED); - return; - } - - if (type != GUILD_CHARTER_TYPE) - { - if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); - return; - } - - uint8 slot = ArenaTeam::GetSlotByType(type); - if (slot >= MAX_ARENA_SLOT) - return; - - if (_player->GetArenaTeamId(slot)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); - return; - } - - if (_player->GetArenaTeamIdInvited()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); - return; - } - } - else - { - if (_player->GetGuildId()) - { - Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, _player->GetName()); - return; - } - if (_player->GetGuildIdInvited()) - { - Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName()); - return; - } - } - - if (++signs > type) // client signs maximum - return; - - //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account - //not allow sign another player from already sign player account - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionGuid)); - - if (result) - { - WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); - data << uint64(petitionGuid); - data << uint64(_player->GetGUID()); - data << (uint32)PETITION_SIGN_ALREADY_SIGNED; - - // close at signer side - SendPacket(&data); - - // update for owner if online - if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid)) - owner->GetSession()->SendPacket(&data); - return; - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); - - stmt->setUInt32(0, GUID_LOPART(ownerGuid)); - stmt->setUInt32(1, GUID_LOPART(petitionGuid)); - stmt->setUInt32(2, playerGuid); - stmt->setUInt32(3, GetAccountId()); - - CharacterDatabase.Execute(stmt); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionGuid), _player->GetName(), playerGuid, GetAccountId()); - - WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); - data << uint64(petitionGuid); - data << uint64(_player->GetGUID()); - data << uint32(PETITION_SIGN_OK); - - // close at signer side - SendPacket(&data); - - // update signs count on charter, required testing... - //Item* item = _player->GetItemByGuid(petitionguid)); - //if (item) - // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); - - // update for owner if online - if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid)) - owner->GetSession()->SendPacket(&data); -} - -void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode MSG_PETITION_DECLINE"); // ok - - uint64 petitionguid; - uint64 ownerguid; - recv_data >> petitionguid; // petition guid - sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); - - QueryResult result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if (!result) - return; - - Field* fields = result->Fetch(); - ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - - Player* owner = ObjectAccessor::FindPlayer(ownerguid); - if (owner) // petition owner online - { - WorldPacket data(MSG_PETITION_DECLINE, 8); - data << uint64(_player->GetGUID()); - owner->GetSession()->SendPacket(&data); - } -} - -void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_OFFER_PETITION"); // ok - - uint8 signs = 0; - uint64 petitionguid, plguid; - uint32 type, junk; - Player* player; - recv_data >> junk; // this is not petition type! - recv_data >> petitionguid; // petition guid - recv_data >> plguid; // player guid - - player = ObjectAccessor::FindPlayer(plguid); - if (!player) - return; - - QueryResult result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if (!result) - return; - - Field* fields = result->Fetch(); - type = fields[0].GetUInt8(); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); - - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam()) - { - if (type != GUILD_CHARTER_TYPE) - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - else - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NOT_ALLIED); - return; - } - - if (type != GUILD_CHARTER_TYPE) - { - if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - // player is too low level to join an arena team - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S); - return; - } - - uint8 slot = ArenaTeam::GetSlotByType(type); - if (slot >= MAX_ARENA_SLOT) - return; - - if (player->GetArenaTeamId(slot)) - { - // player is already in an arena team - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); - return; - } - - if (player->GetArenaTeamIdInvited()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); - return; - } - } - else - { - if (player->GetGuildId()) - { - Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, _player->GetName()); - return; - } - - if (player->GetGuildIdInvited()) - { - Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName()); - return; - } - } - - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - // result == NULL also correct charter without signs - if (result) - signs = uint8(result->GetRowCount()); - - WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12)); - data << uint64(petitionguid); // petition guid - data << uint64(_player->GetGUID()); // owner guid - data << uint32(GUID_LOPART(petitionguid)); // guild guid - data << uint8(signs); // sign's count - - for (uint8 i = 1; i <= signs; ++i) - { - Field* fields2 = result->Fetch(); - plguid = fields2[0].GetUInt64(); - - data << uint64(plguid); // Player GUID - data << uint32(0); // there 0 ... - - result->NextRow(); - } - - player->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); - - // Get petition guid from packet - WorldPacket data; - uint64 petitionGuid; - - recv_data >> petitionGuid; - - // Check if player really has the required petition charter - Item* item = _player->GetItemByGuid(petitionGuid); - if (!item) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u turned in by %u", GUID_LOPART(petitionGuid), _player->GetGUIDLow()); - - // Get petition data from db - uint32 ownerguidlo; - uint32 type; - std::string name; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); - stmt->setUInt32(0, GUID_LOPART(petitionGuid)); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) - { - Field* fields = result->Fetch(); - ownerguidlo = fields[0].GetUInt32(); - name = fields[1].GetString(); - type = fields[2].GetUInt8(); - } - else - { - sLog->outError("Player %s (guid: %u) tried to turn in petition (guid: %u) that is not present in the database", _player->GetName(), _player->GetGUIDLow(), GUID_LOPART(petitionGuid)); - return; - } - - // Only the petition owner can turn in the petition - if (_player->GetGUIDLow() != ownerguidlo) - return; - - // Petition type (guild/arena) specific checks - if (type == GUILD_CHARTER_TYPE) - { - // Check if player is already in a guild - if (_player->GetGuildId()) - { - data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; - _player->GetSession()->SendPacket(&data); - return; - } - - // Check if guild name is already taken - if (sGuildMgr->GetGuildByName(name)) - { - Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name); - return; - } - } - else - { - // Check for valid arena bracket (2v2, 3v3, 5v5) - uint8 slot = ArenaTeam::GetSlotByType(type); - if (slot >= MAX_ARENA_SLOT) - return; - - // Check if player is already in an arena team - if (_player->GetArenaTeamId(slot)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - - // Check if arena team name is already taken - if (sArenaTeamMgr->GetArenaTeamByName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); - return; - } - } - - // Get petition signatures from db - uint8 signatures; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); - stmt->setUInt32(0, GUID_LOPART(petitionGuid)); - result = CharacterDatabase.Query(stmt); - - if (result) - signatures = uint8(result->GetRowCount()); - else - signatures = 0; - - uint32 requiredSignatures; - if (type == GUILD_CHARTER_TYPE) - requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); - else - requiredSignatures = type-1; - - // Notify player if signatures are missing - if (signatures < requiredSignatures) - { - data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; - SendPacket(&data); - return; - } - - // Proceed with guild/arena team creation - - // Delete charter item - _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); - - if (type == GUILD_CHARTER_TYPE) - { - // Create guild - Guild* guild = new Guild; - - if (!guild->Create(_player, name)) - { - delete guild; - return; - } - - // Register guild and add guild master - sGuildMgr->AddGuild(guild); - - // Add members from signatures - for (uint8 i = 0; i < signatures; ++i) - { - Field* fields = result->Fetch(); - guild->AddMember(MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER)); - result->NextRow(); - } - } - else - { - // Receive the rest of the packet in arena team creation case - uint32 background, icon, iconcolor, border, bordercolor; - recv_data >> background >> icon >> iconcolor >> border >> bordercolor; - - // Create arena team - ArenaTeam* arenaTeam = new ArenaTeam(); - - if (!arenaTeam->Create(_player->GetGUID(), type, name, background, icon, iconcolor, border, bordercolor)) - { - delete arenaTeam; - return; - } - - // Register arena team - sArenaTeamMgr->AddArenaTeam(arenaTeam); - sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitonsHandler: Arena team (guid: %u) added to ObjectMgr", arenaTeam->GetId()); - - // Add members - for (uint8 i = 0; i < signatures; ++i) - { - Field* fields = result->Fetch(); - uint32 memberGUID = fields[0].GetUInt32(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitionsHandler: Adding arena team (guid: %u) member %u", arenaTeam->GetId(), memberGUID); - arenaTeam->AddMember(MAKE_NEW_GUID(memberGUID, 0, HIGHGUID_PLAYER)); - result->NextRow(); - } - } - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); - trans->PAppend("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); - CharacterDatabase.CommitTransaction(trans); - - // created - sLog->outDebug(LOG_FILTER_NETWORKIO, "TURN IN PETITION GUID %u", GUID_LOPART(petitionGuid)); - - data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - data << (uint32)PETITION_TURN_OK; - SendPacket(&data); -} - -void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received CMSG_PETITION_SHOWLIST"); - - uint64 guid; - recv_data >> guid; - - SendPetitionShowList(guid); -} - -void WorldSession::SendPetitionShowList(uint64 guid) -{ - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6); - data << guid; // npc guid - - if (creature->isTabardDesigner()) - { - data << uint8(1); // count - data << uint32(1); // index - data << uint32(GUILD_CHARTER); // charter entry - data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(GUILD_CHARTER_COST); // charter cost - data << uint32(0); // unknown - data << uint32(9); // required signs? - } - else - { - data << uint8(3); // count - // 2v2 - data << uint32(1); // index - data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry - data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost - data << uint32(2); // unknown - data << uint32(2); // required signs? - // 3v3 - data << uint32(2); // index - data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry - data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost - data << uint32(3); // unknown - data << uint32(3); // required signs? - // 5v5 - data << uint32(3); // index - data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry - data << uint32(CHARTER_DISPLAY_ID); // charter display id - data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost - data << uint32(5); // unknown - data << uint32(5); // required signs? - } - - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "Sent SMSG_PETITION_SHOWLIST"); -} diff --git a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp deleted file mode 100755 index abb62fb0185..00000000000 --- a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp +++ /dev/null @@ -1,484 +0,0 @@ -/* - * 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 "Language.h" -#include "DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "UpdateMask.h" -#include "NPCHandler.h" -#include "Pet.h" -#include "MapManager.h" - -void WorldSession::SendNameQueryOpcode(uint64 guid) -{ - Player* player = NULL; - const CharacterNameData* nameData = sWorld->GetCharacterNameData(GUID_LOPART(guid)); - if (nameData) - player = ObjectAccessor::FindPlayer(guid); - - // guess size - WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10)); - data.appendPackGUID(guid); - data << uint8(0); // added in 3.1 - if (nameData) - { - data << nameData->m_name; // played name - data << uint8(0); // realm name for cross realm BG usage - data << uint8(nameData->m_race); - data << uint8(nameData->m_gender); - data << uint8(nameData->m_class); - } - else - { - data << std::string(GetTrinityString(LANG_NON_EXIST_CHARACTER)); - data << uint32(0); - } - - if (player) - { - if (DeclinedName const* names = player->GetDeclinedNames()) - { - data << uint8(1); // is declined - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << names->name[i]; - } - else - data << uint8(0); // is not declined - } - else //TODO: decline names may also need to be stored in char name data - data << uint8(0); - - SendPacket(&data); -} - -void WorldSession::HandleNameQueryOpcode(WorldPacket& recv_data) -{ - uint64 guid; - - recv_data >> guid; - - // This is disable by default to prevent lots of console spam - // sLog->outString("HandleNameQueryOpcode %u", guid); - - SendNameQueryOpcode(guid); -} - -void WorldSession::HandleQueryTimeOpcode(WorldPacket & /*recv_data*/) -{ - SendQueryTimeResponse(); -} - -void WorldSession::SendQueryTimeResponse() -{ - WorldPacket data(SMSG_QUERY_TIME_RESPONSE, 4+4); - data << uint32(time(NULL)); - data << uint32(sWorld->GetNextDailyQuestsResetTime() - time(NULL)); - SendPacket(&data); -} - -/// Only _static_ data is sent in this packet !!! -void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) -{ - uint32 entry; - recv_data >> entry; - uint64 guid; - recv_data >> guid; - - CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(entry); - if (ci) - { - - std::string Name, SubName; - Name = ci->Name; - SubName = ci->SubName; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(entry)) - { - ObjectMgr::GetLocaleString(cl->Name, loc_idx, Name); - ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName); - } - } - sLog->outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); - // guess size - WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); - data << uint32(entry); // creature entry - data << Name; - - for (int i = 0; i < 7; i++) - data << uint8(0); // name2, ..., name8 - - data << SubName; - data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 - data << uint32(ci->type_flags); // flags - data << uint32(ci->type_flags2); // unknown meaning - data << uint32(ci->type); // CreatureType.dbc - data << uint32(ci->family); // CreatureFamily.dbc - data << uint32(ci->rank); // Creature Rank (elite, boss, etc) - data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit - data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit - data << uint32(ci->Modelid1); // Modelid1 - data << uint32(ci->Modelid2); // Modelid2 - data << uint32(ci->Modelid3); // Modelid3 - data << uint32(ci->Modelid4); // Modelid4 - data << float(ci->ModHealth); // dmg/hp modifier - data << float(ci->ModMana); // dmg/mana modifier - data << uint8(ci->RacialLeader); - for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) - data << uint32(ci->questItems[i]); // itemId[6], quest drop - data << uint32(ci->movementId); // CreatureMovementInfo.dbc - data << uint32(ci->expansionUnknown); // unknown meaning - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); - } - else - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)", - GUID_LOPART(guid), entry); - WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 4); - data << uint32(entry | 0x80000000); - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); - } -} - -/// Only _static_ data is sent in this packet !!! -void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) -{ - uint32 entry; - recv_data >> entry; - uint64 guid; - recv_data >> guid; - - const GameObjectTemplate* info = sObjectMgr->GetGameObjectTemplate(entry); - if (info) - { - std::string Name; - std::string IconName; - std::string CastBarCaption; - - Name = info->name; - IconName = info->IconName; - CastBarCaption = info->castBarCaption; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - if (GameObjectLocale const* gl = sObjectMgr->GetGameObjectLocale(entry)) - { - ObjectMgr::GetLocaleString(gl->Name, loc_idx, Name); - ObjectMgr::GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption); - } - } - sLog->outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); - WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); - data << uint32(entry); - data << uint32(info->type); - data << uint32(info->displayId); - data << Name; - data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 - data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) - data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") - data << info->unk1; // 2.0.3, string - data.append(info->raw.data, MAX_GAMEOBJECT_DATA); - data << float(info->size); // go size - for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i) - data << uint32(info->questItems[i]); // itemId[6], quest drop - data << int32(info->unkInt32); // 4.x, unknown - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); - } - else - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", - GUID_LOPART(guid), entry); - WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 4); - data << uint32(entry | 0x80000000); - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); - } -} - -void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDetail("WORLD: Received MSG_CORPSE_QUERY"); - - Corpse* corpse = GetPlayer()->GetCorpse(); - - if (!corpse) - { - WorldPacket data(MSG_CORPSE_QUERY, 1); - data << uint8(0); // corpse not found - SendPacket(&data); - return; - } - - uint32 mapid = corpse->GetMapId(); - float x = corpse->GetPositionX(); - float y = corpse->GetPositionY(); - float z = corpse->GetPositionZ(); - uint32 corpsemapid = mapid; - - // if corpse at different map - if (mapid != _player->GetMapId()) - { - // search entrance map for proper show entrance - if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapid)) - { - if (corpseMapEntry->IsDungeon() && corpseMapEntry->entrance_map >= 0) - { - // if corpse map have entrance - if (Map const* entranceMap = sMapMgr->CreateBaseMap(corpseMapEntry->entrance_map)) - { - mapid = corpseMapEntry->entrance_map; - x = corpseMapEntry->entrance_x; - y = corpseMapEntry->entrance_y; - z = entranceMap->GetHeight(x, y, MAX_HEIGHT); - } - } - } - } - - WorldPacket data(MSG_CORPSE_QUERY, 1+(6*4)); - data << uint8(1); // corpse found - data << int32(mapid); - data << float(x); - data << float(y); - data << float(z); - data << int32(corpsemapid); - data << uint32(0); // unknown - SendPacket(&data); -} - -void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) -{ - uint32 textID; - uint64 guid; - - recv_data >> textID; - sLog->outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); - - recv_data >> guid; - GetPlayer()->SetSelection(guid); - - GossipText const* pGossip = sObjectMgr->GetGossipText(textID); - - WorldPacket data(SMSG_NPC_TEXT_UPDATE, 100); // guess size - data << textID; - - if (!pGossip) - { - for (uint32 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) - { - data << float(0); - data << "Greetings $N"; - data << "Greetings $N"; - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - } - } - else - { - std::string Text_0[MAX_LOCALES], Text_1[MAX_LOCALES]; - for (int i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) - { - Text_0[i]=pGossip->Options[i].Text_0; - Text_1[i]=pGossip->Options[i].Text_1; - } - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - if (NpcTextLocale const* nl = sObjectMgr->GetNpcTextLocale(textID)) - { - for (int i = 0; i < MAX_LOCALES; ++i) - { - ObjectMgr::GetLocaleString(nl->Text_0[i], loc_idx, Text_0[i]); - ObjectMgr::GetLocaleString(nl->Text_1[i], loc_idx, Text_1[i]); - } - } - } - - for (int i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i) - { - data << pGossip->Options[i].Probability; - - if (Text_0[i].empty()) - data << Text_1[i]; - else - data << Text_0[i]; - - if (Text_1[i].empty()) - data << Text_0[i]; - else - data << Text_1[i]; - - data << pGossip->Options[i].Language; - - for (int j = 0; j < MAX_GOSSIP_TEXT_EMOTES; ++j) - { - data << pGossip->Options[i].Emotes[j]._Delay; - data << pGossip->Options[i].Emotes[j]._Emote; - } - } - } - - SendPacket(&data); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_NPC_TEXT_UPDATE"); -} - -/// Only _static_ data is sent in this packet !!! -void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) -{ - sLog->outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY"); - - uint32 pageID; - recv_data >> pageID; - recv_data.read_skip<uint64>(); // guid - - while (pageID) - { - PageText const* pageText = sObjectMgr->GetPageText(pageID); - // guess size - WorldPacket data(SMSG_PAGE_TEXT_QUERY_RESPONSE, 50); - data << pageID; - - if (!pageText) - { - data << "Item page missing."; - data << uint32(0); - pageID = 0; - } - else - { - std::string Text = pageText->Text; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - if (PageTextLocale const* player = sObjectMgr->GetPageTextLocale(pageID)) - ObjectMgr::GetLocaleString(player->Text, loc_idx, Text); - - data << Text; - data << uint32(pageText->NextPage); - pageID = pageText->NextPage; - } - SendPacket(&data); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE"); - } -} - -void WorldSession::HandleCorpseMapPositionQuery(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_CORPSE_MAP_POSITION_QUERY"); - - uint32 unk; - recv_data >> unk; - - WorldPacket data(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, 4+4+4+4); - data << float(0); - data << float(0); - data << float(0); - data << float(0); - SendPacket(&data); -} - -void WorldSession::HandleQuestPOIQuery(WorldPacket& recv_data) -{ - uint32 count; - recv_data >> count; // quest count, max=25 - // 4.3 struct: count, byte, byte, byte, questIds[] - - if (count >= MAX_QUEST_LOG_SIZE) - { - recv_data.rfinish(); - return; - } - - WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4+(4+4)*count); - data << uint32(count); // count - - for (uint32 i = 0; i < count; ++i) - { - uint32 questId; - recv_data >> questId; // quest id - - bool questOk = false; - - uint16 questSlot = _player->FindQuestSlot(questId); - - if (questSlot != MAX_QUEST_LOG_SIZE) - questOk =_player->GetQuestSlotQuestId(questSlot) == questId; - - if (questOk) - { - QuestPOIVector const* POI = sObjectMgr->GetQuestPOIVector(questId); - - if (POI) - { - data << uint32(questId); // quest ID - data << uint32(POI->size()); // POI count - - for (QuestPOIVector::const_iterator itr = POI->begin(); itr != POI->end(); ++itr) - { - data << uint32(itr->Id); // POI index - data << int32(itr->ObjectiveIndex); // objective index - data << uint32(itr->MapId); // mapid - data << uint32(itr->AreaId); // areaid - data << uint32(itr->Unk2); // unknown - data << uint32(itr->Unk3); // unknown - data << uint32(itr->Unk4); // unknown - data << uint32(itr->points.size()); // POI points count - - for (std::vector<QuestPOIPoint>::const_iterator itr2 = itr->points.begin(); itr2 != itr->points.end(); ++itr2) - { - data << int32(itr2->x); // POI point x - data << int32(itr2->y); // POI point y - } - } - } - else - { - data << uint32(questId); // quest ID - data << uint32(0); // POI count - } - } - else - { - data << uint32(questId); // quest ID - data << uint32(0); // POI count - } - } - - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp b/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp deleted file mode 100755 index a3debe82ac1..00000000000 --- a/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp +++ /dev/null @@ -1,780 +0,0 @@ -/* - * 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 "Log.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "GossipDef.h" -#include "QuestDef.h" -#include "ObjectAccessor.h" -#include "Group.h" -#include "Battleground.h" -#include "BattlegroundAV.h" -#include "ScriptMgr.h" -#include "GameObjectAI.h" - -void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - uint32 questStatus = DIALOG_STATUS_NONE; - uint32 defstatus = DIALOG_STATUS_NONE; - - Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!questgiver) - { - sLog->outDetail("Error in CMSG_QUESTGIVER_STATUS_QUERY, called for not found questgiver (Typeid: %u GUID: %u)", GuidHigh2TypeId(GUID_HIPART(guid)), GUID_LOPART(guid)); - return; - } - - switch (questgiver->GetTypeId()) - { - case TYPEID_UNIT: - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", uint32(GUID_LOPART(guid))); - Creature* cr_questgiver=questgiver->ToCreature(); - if (!cr_questgiver->IsHostileTo(_player)) // not show quest status to enemies - { - questStatus = sScriptMgr->GetDialogStatus(_player, cr_questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, cr_questgiver, defstatus); - } - break; - } - case TYPEID_GAMEOBJECT: - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", uint32(GUID_LOPART(guid))); - GameObject* go_questgiver=(GameObject*)questgiver; - questStatus = sScriptMgr->GetDialogStatus(_player, go_questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, go_questgiver, defstatus); - break; - } - default: - sLog->outError("QuestGiver called for unexpected type %u", questgiver->GetTypeId()); - break; - } - - //inform client about status of quest - _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); -} - -void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); - - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!creature) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", - GUID_LOPART(guid)); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - // Stop the npc if moving - creature->StopMoving(); - - if (sScriptMgr->OnGossipHello(_player, creature)) - return; - - _player->PrepareGossipMenu(creature, creature->GetCreatureInfo()->GossipMenuId, true); - _player->SendPreparedGossip(creature); - - creature->AI()->sGossipHello(_player); -} - -void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 quest; - uint32 unk1; - recv_data >> guid >> quest >> unk1; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), quest, unk1); - - Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM|TYPEMASK_PLAYER); - - // no or incorrect quest giver - if (!pObject || (pObject->GetTypeId() != TYPEID_PLAYER && !pObject->hasQuest(quest)) || - (pObject->GetTypeId() == TYPEID_PLAYER && !pObject->ToPlayer()->CanShareQuest(quest))) - { - _player->PlayerTalkClass->SendCloseGossip(); - _player->SetDivider(0); - return; - } - - // some kind of WPE protection - if (!_player->CanInteractWithQuestGiver(pObject)) - return; - - Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest); - if (qInfo) - { - // prevent cheating - if (!GetPlayer()->CanTakeQuest(qInfo, true)) - { - _player->PlayerTalkClass->SendCloseGossip(); - _player->SetDivider(0); - return; - } - - if (_player->GetDivider() != 0) - { - Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); - if (player) - { - player->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); - _player->SetDivider(0); - } - } - - if (_player->CanAddQuest(qInfo, true)) - { - _player->AddQuest(qInfo, pObject); - - if (qInfo->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) - { - if (Group* group = _player->GetGroup()) - { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* player = itr->getSource(); - - if (!player || player == _player) // not self - continue; - - if (player->CanTakeQuest(qInfo, true)) - { - player->SetDivider(_player->GetGUID()); - - //need confirmation that any gossip window will close - player->PlayerTalkClass->SendCloseGossip(); - - _player->SendQuestConfirmAccept(qInfo, player); - } - } - } - } - - if (_player->CanCompleteQuest(quest)) - _player->CompleteQuest(quest); - - switch (pObject->GetTypeId()) - { - case TYPEID_UNIT: - sScriptMgr->OnQuestAccept(_player, (pObject->ToCreature()), qInfo); - (pObject->ToCreature())->AI()->sQuestAccept(_player, qInfo); - break; - case TYPEID_ITEM: - case TYPEID_CONTAINER: - { - sScriptMgr->OnQuestAccept(_player, ((Item*)pObject), qInfo); - - // destroy not required for quest finish quest starting item - bool destroyItem = true; - for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - { - if ((qInfo->RequiredItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetTemplate()->MaxCount > 0)) - { - destroyItem = false; - break; - } - } - - if (destroyItem) - _player->DestroyItem(((Item*)pObject)->GetBagSlot(), ((Item*)pObject)->GetSlot(), true); - - break; - } - case TYPEID_GAMEOBJECT: - sScriptMgr->OnQuestAccept(_player, ((GameObject*)pObject), qInfo); - (pObject->ToGameObject())->AI()->QuestAccept(_player, qInfo); - break; - default: - break; - } - _player->PlayerTalkClass->SendCloseGossip(); - - if (qInfo->GetSrcSpell() > 0) - _player->CastSpell(_player, qInfo->GetSrcSpell(), true); - - return; - } - } - - _player->PlayerTalkClass->SendCloseGossip(); -} - -void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 questId; - uint8 unk1; - recv_data >> guid >> questId >> unk1; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_QUERY_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), questId, unk1); - - // Verify that the guid is valid and is a questgiver or involved in the requested quest - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); - if (!object || (!object->hasQuest(questId) && !object->hasInvolvedQuest(questId))) - { - _player->PlayerTalkClass->SendCloseGossip(); - return; - } - - Quest const* quest = sObjectMgr->GetQuestTemplate(questId); - if (quest) - { - // not sure here what should happen to quests with QUEST_FLAGS_AUTOCOMPLETE - // if this breaks them, add && object->GetTypeId() == TYPEID_ITEM to this check - // item-started quests never have that flag - if (!_player->CanTakeQuest(quest, true)) - return; - - if (quest->IsAutoAccept() && _player->CanAddQuest(quest, true)) - { - _player->AddQuest(quest, object); - if (_player->CanCompleteQuest(questId)) - _player->CompleteQuest(questId); - } - - if (quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE)) - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true); - else - _player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, object->GetGUID(), true); - } -} - -void WorldSession::HandleQuestQueryOpcode(WorldPacket & recv_data) -{ - if (!_player) - return; - - uint32 quest; - recv_data >> quest; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_QUERY quest = %u", quest); - - Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest); - if (pQuest) - { - _player->PlayerTalkClass->SendQuestQueryResponse(pQuest); - } -} - -void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) -{ - uint32 questId, reward; - uint64 guid; - recv_data >> guid >> questId >> reward; - - if (reward >= QUEST_REWARD_CHOICES_COUNT) - { - sLog->outError("Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (probably packet hacking)", _player->GetName(), _player->GetGUIDLow(), reward); - return; - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u", uint32(GUID_LOPART(guid)), questId, reward); - - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!object || !object->hasInvolvedQuest(questId)) - return; - - // some kind of WPE protection - if (!_player->CanInteractWithQuestGiver(object)) - return; - - if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) - { - if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) || - (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete())) - { - sLog->outError("HACK ALERT: Player %s (guid: %u) is trying to complete quest (id: %u) but he has no right to do it!", - _player->GetName(), _player->GetGUIDLow(), questId); - return; - } - if (_player->CanRewardQuest(quest, reward, true)) - { - _player->RewardQuest(quest, reward, object); - - switch (object->GetTypeId()) - { - case TYPEID_UNIT: - if (!(sScriptMgr->OnQuestReward(_player, (object->ToCreature()), quest, reward))) - { - // Send next quest - if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) - { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(quest, true)) - { - _player->AddQuest(nextQuest, object); - if (_player->CanCompleteQuest(nextQuest->GetQuestId())) - _player->CompleteQuest(nextQuest->GetQuestId()); - } - - _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); - } - - (object->ToCreature())->AI()->sQuestReward(_player, quest, reward); - } - break; - case TYPEID_GAMEOBJECT: - if (!sScriptMgr->OnQuestReward(_player, ((GameObject*)object), quest, reward)) - { - // Send next quest - if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) - { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(quest, true)) - { - _player->AddQuest(nextQuest, object); - if (_player->CanCompleteQuest(nextQuest->GetQuestId())) - _player->CompleteQuest(nextQuest->GetQuestId()); - } - - _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); - } - - object->ToGameObject()->AI()->QuestReward(_player, quest, reward); - } - break; - default: - break; - } - } - else - _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); - } -} - -void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket & recv_data) -{ - uint32 quest; - uint64 guid; - recv_data >> guid >> quest; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %u, quest = %u", uint32(GUID_LOPART(guid)), quest); - - Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!pObject || !pObject->hasInvolvedQuest(quest)) - return; - - // some kind of WPE protection - if (!_player->CanInteractWithQuestGiver(pObject)) - return; - - if (_player->CanCompleteQuest(quest)) - _player->CompleteQuest(quest); - - if (_player->GetQuestStatus(quest) != QUEST_STATUS_COMPLETE) - return; - - if (Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest)) - _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); -} - -void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_CANCEL"); - - _player->PlayerTalkClass->SendCloseGossip(); -} - -void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recv_data) -{ - uint8 slot1, slot2; - recv_data >> slot1 >> slot2; - - if (slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = %u, slot 2 = %u", slot1, slot2); - - GetPlayer()->SwapQuestSlot(slot1, slot2); -} - -void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) -{ - uint8 slot; - recv_data >> slot; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = %u", slot); - - if (slot < MAX_QUEST_LOG_SIZE) - { - if (uint32 quest = _player->GetQuestSlotQuestId(slot)) - { - if (!_player->TakeQuestSourceItem(quest, true)) - return; // can't un-equip some items, reject quest cancel - - if (const Quest *pQuest = sObjectMgr->GetQuestTemplate(quest)) - { - if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) - _player->RemoveTimedQuest(quest); - } - - _player->TakeQuestSourceItem(quest, true); // remove quest src item from player - _player->RemoveActiveQuest(quest); - _player->GetAchievementMgr().RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest); - - sLog->outDetail("Player %u abandoned quest %u", _player->GetGUIDLow(), quest); - } - - _player->SetQuestSlot(slot, 0); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1); - } -} - -void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData) -{ - uint32 questId; - recvData >> questId; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT questId = %u", questId); - - if (const Quest* quest = sObjectMgr->GetQuestTemplate(questId)) - { - if (!quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) - return; - - Player* pOriginalPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); - - if (!pOriginalPlayer) - return; - - if (quest->IsRaidQuest()) - { - if (!_player->IsInSameRaidWith(pOriginalPlayer)) - return; - } - else - { - if (!_player->IsInSameGroupWith(pOriginalPlayer)) - return; - } - - if (_player->CanAddQuest(quest, true)) - _player->AddQuest(quest, NULL); // NULL, this prevent DB script from duplicate running - - _player->SetDivider(0); - } -} - -void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) -{ - uint32 questId; - uint64 playerGuid; - int8 unkByte; - recv_data >> playerGuid >> questId >> unkByte; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u", uint32(GUID_LOPART(playerGuid)), questId); - - Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, playerGuid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!object || !object->hasInvolvedQuest(questId)) - return; - - // some kind of WPE protection - if (!_player->CanInteractWithQuestGiver(object)) - return; - - Quest const* quest = sObjectMgr->GetQuestTemplate(questId); - if (quest) - { - if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId)==QUEST_STATUS_NONE) - { - sLog->outError("Possible hacking attempt: Player %s [playerGuid: %u] tried to complete questId [entry: %u] without being in possession of the questId!", - _player->GetName(), _player->GetGUIDLow(), questId); - return; - } - // TODO: need a virtual function - if (_player->InBattleground()) - if (Battleground* bg = _player->GetBattleground()) - if (bg->GetTypeID() == BATTLEGROUND_AV) - ((BattlegroundAV*)bg)->HandleQuestComplete(questId, _player); - - if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE) - { - if (quest->IsRepeatable()) - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanCompleteRepeatableQuest(quest), false); - else - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false); - } - else - { - if (quest->GetReqItemsCount()) // some items required - _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false); - else // no items required - _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, playerGuid, true); - } - } -} - -void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH"); -} - -void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) -{ - uint32 questId; - recvPacket >> questId; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PUSHQUESTTOPARTY questId = %u", questId); - - if (Quest const* pQuest = sObjectMgr->GetQuestTemplate(questId)) - { - if (Group* group = _player->GetGroup()) - { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* player = itr->getSource(); - - if (!player || player == _player) // skip self - continue; - - _player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_SHARING_QUEST); - - if (!player->SatisfyQuestStatus(pQuest, false)) - { - _player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_HAVE_QUEST); - continue; - } - - if (player->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) - { - _player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_FINISH_QUEST); - continue; - } - - if (!player->CanTakeQuest(pQuest, false)) - { - _player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_CANT_TAKE_QUEST); - continue; - } - - if (!player->SatisfyQuestLog(false)) - { - _player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_LOG_FULL); - continue; - } - - if (player->GetDivider() != 0) - { - _player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_BUSY); - continue; - } - - player->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, _player->GetGUID(), true); - player->SetDivider(_player->GetGUID()); - } - } - } -} - -void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) -{ - uint64 guid; - uint8 msg; - recvPacket >> guid >> msg; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_QUEST_PUSH_RESULT"); - - if (_player->GetDivider() != 0) - { - Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); - if (player) - { - WorldPacket data(MSG_QUEST_PUSH_RESULT, (8+1)); - data << uint64(guid); - data << uint8(msg); // valid values: 0-8 - player->GetSession()->SendPacket(&data); - _player->SetDivider(0); - } - } -} - -uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver, uint32 defstatus) -{ - uint32 result = defstatus; - - QuestRelationBounds qr; - QuestRelationBounds qir; - - switch (questgiver->GetTypeId()) - { - case TYPEID_GAMEOBJECT: - { - qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry()); - qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry()); - break; - } - case TYPEID_UNIT: - { - qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry()); - qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry()); - break; - } - default: - //its imposible, but check ^) - sLog->outError("Warning: GetDialogStatus called for unexpected type %u", questgiver->GetTypeId()); - return DIALOG_STATUS_NONE; - } - - for (QuestRelations::const_iterator i = qir.first; i != qir.second; ++i) - { - uint32 result2 = 0; - uint32 quest_id = i->second; - Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id); - if (!pQuest) continue; - - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, pQuest->GetQuestId()); - if (!sConditionMgr->IsPlayerMeetToConditions(player, conditions)) - continue; - - QuestStatus status = player->GetQuestStatus(quest_id); - if ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(quest_id)) || - (pQuest->IsAutoComplete() && player->CanTakeQuest(pQuest, false))) - { - if (pQuest->IsAutoComplete() && pQuest->IsRepeatable()) - result2 = DIALOG_STATUS_REWARD_REP; - else - result2 = DIALOG_STATUS_REWARD; - } - else if (status == QUEST_STATUS_INCOMPLETE) - result2 = DIALOG_STATUS_INCOMPLETE; - - if (result2 > result) - result = result2; - } - - for (QuestRelations::const_iterator i = qr.first; i != qr.second; ++i) - { - uint32 result2 = 0; - uint32 quest_id = i->second; - Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id); - if (!pQuest) - continue; - - ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, pQuest->GetQuestId()); - if (!sConditionMgr->IsPlayerMeetToConditions(player, conditions)) - continue; - - QuestStatus status = player->GetQuestStatus(quest_id); - if (status == QUEST_STATUS_NONE) - { - if (player->CanSeeStartQuest(pQuest)) - { - if (player->SatisfyQuestLevel(pQuest, false)) - { - if (pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && player->IsQuestRewarded(quest_id))) - result2 = DIALOG_STATUS_REWARD_REP; - else if (player->getLevel() <= ((player->GetQuestLevel(pQuest) == -1) ? player->getLevel() : player->GetQuestLevel(pQuest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) - { - if (pQuest->HasFlag(QUEST_FLAGS_DAILY) || pQuest->HasFlag(QUEST_FLAGS_WEEKLY)) - result2 = DIALOG_STATUS_AVAILABLE_REP; - else - result2 = DIALOG_STATUS_AVAILABLE; - } - else - result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; - } - else - result2 = DIALOG_STATUS_UNAVAILABLE; - } - } - - if (result2 > result) - result = result2; - } - - return result; -} - -void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); - - uint32 count = 0; - - WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4 + 8 + 4); - data << uint32(count); // placeholder - - for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) - { - uint32 questStatus = DIALOG_STATUS_NONE; - uint32 defstatus = DIALOG_STATUS_NONE; - - if (IS_CRE_OR_VEH_OR_PET_GUID(*itr)) - { - // need also pet quests case support - Creature* questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(), *itr); - if (!questgiver || questgiver->IsHostileTo(_player)) - continue; - if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) - continue; - questStatus = sScriptMgr->GetDialogStatus(_player, questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, questgiver, defstatus); - - data << uint64(questgiver->GetGUID()); - data << uint32(questStatus); - ++count; - } - else if (IS_GAMEOBJECT_GUID(*itr)) - { - GameObject* questgiver = GetPlayer()->GetMap()->GetGameObject(*itr); - if (!questgiver) - continue; - if (questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) - continue; - questStatus = sScriptMgr->GetDialogStatus(_player, questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, questgiver, defstatus); - - data << uint64(questgiver->GetGUID()); - data << uint32(questStatus); - ++count; - } - } - - data.put<uint32>(0, count); // write real count - SendPacket(&data); -} - -void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recvData*/) -{ - size_t rew_count = _player->GetRewardedQuestCount(); - - WorldPacket data(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4 + 4 * rew_count); - data << uint32(rew_count); - - const RewardedQuestSet &rewQuests = _player->getRewardedQuests(); - for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr) - data << uint32(*itr); - - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/ReferAFriendHandler.cpp b/src/server/game/Server/Protocol/Handlers/ReferAFriendHandler.cpp deleted file mode 100644 index 58d425ddf98..00000000000 --- a/src/server/game/Server/Protocol/Handlers/ReferAFriendHandler.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2011 TrinityCore <http://www.trinitycore.org/> - * - * 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 "WorldSession.h" -#include "Player.h" -#include "ObjectMgr.h" -#include "Opcodes.h" -#include "Log.h" - -void WorldSession::HandleGrantLevel(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GRANT_LEVEL"); - - uint64 guid; - recv_data.readPackGUID(guid); - - Player* target = ObjectAccessor::GetObjectInWorld(guid, _player); - - // check cheating - uint8 levels = _player->GetGrantableLevels(); - uint8 error = 0; - if (!target) - error = ERR_REFER_A_FRIEND_NO_TARGET; - else if (levels == 0) - error = ERR_REFER_A_FRIEND_INSUFFICIENT_GRANTABLE_LEVELS; - else if (GetRecruiterId() != target->GetSession()->GetAccountId()) - error = ERR_REFER_A_FRIEND_NOT_REFERRED_BY; - else if (target->GetTeamId() != _player->GetTeamId()) - error = ERR_REFER_A_FRIEND_DIFFERENT_FACTION; - else if (target->getLevel() >= _player->getLevel()) - error = ERR_REFER_A_FRIEND_TARGET_TOO_HIGH; - else if (target->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL)) - error = ERR_REFER_A_FRIEND_GRANT_LEVEL_MAX_I; - else if (target->GetGroup() != _player->GetGroup()) - error = ERR_REFER_A_FRIEND_NOT_IN_GROUP; - - if (error) { - WorldPacket data(SMSG_REFER_A_FRIEND_FAILURE, 24); - data << uint32(error); - if (error == ERR_REFER_A_FRIEND_NOT_IN_GROUP) - data << target->GetName(); - - SendPacket(&data); - return; - } - - WorldPacket data2(SMSG_PROPOSE_LEVEL_GRANT, 8); - data2.append(_player->GetPackGUID()); - target->GetSession()->SendPacket(&data2); -} - -void WorldSession::HandleAcceptGrantLevel(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ACCEPT_LEVEL_GRANT"); - - uint64 guid; - recv_data.readPackGUID(guid); - - Player* other = ObjectAccessor::GetObjectInWorld(guid, _player); - if (!(other && other->GetSession())) - return; - - if (GetAccountId() != other->GetSession()->GetRecruiterId()) - return; - - if (other->GetGrantableLevels()) - other->SetGrantableLevels(other->GetGrantableLevels() - 1); - else - return; - - _player->GiveLevel(_player->getLevel() + 1); -} diff --git a/src/server/game/Server/Protocol/Handlers/SkillHandler.cpp b/src/server/game/Server/Protocol/Handlers/SkillHandler.cpp deleted file mode 100755 index 2e4ef5cb40d..00000000000 --- a/src/server/game/Server/Protocol/Handlers/SkillHandler.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 "Player.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectAccessor.h" -#include "UpdateMask.h" - -void WorldSession::HandleLearnTalentOpcode(WorldPacket & recv_data) -{ - uint32 talentId, requestedRank; - recv_data >> talentId >> requestedRank; - - if (_player->LearnTalent(talentId, requestedRank)) - _player->SendTalentsInfoData(false); -} - -void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LEARN_PREVIEW_TALENTS"); - - int32 tabPage; - uint32 talentsCount; - recvPacket >> tabPage; // talent tree - - // prevent cheating (selecting new tree with points already in another) - if (tabPage >= 0) // -1 if player already has specialization - { - if (TalentTabEntry const* talentTabEntry = sTalentTabStore.LookupEntry(_player->GetPrimaryTalentTree(_player->GetActiveSpec()))) - { - if (talentTabEntry->tabpage != tabPage) - { - recvPacket.rfinish(); - return; - } - } - } - - recvPacket >> talentsCount; - - uint32 talentId, talentRank; - - for (uint32 i = 0; i < talentsCount; ++i) - { - recvPacket >> talentId >> talentRank; - - if (!_player->LearnTalent(talentId, talentRank)) - { - recvPacket.rfinish(); - break; - } - } - - _player->SendTalentsInfoData(false); -} - -void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_TALENT_WIPE_CONFIRM"); - uint64 guid; - recv_data >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTalentWipeConfirmOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (!_player->ResetTalents()) - { - WorldPacket data(MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent - data << uint64(0); - data << uint32(0); - SendPacket(&data); - return; - } - - _player->SendTalentsInfoData(false); - unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect" -} - -void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recv_data) -{ - uint32 skillId; - recv_data >> skillId; - GetPlayer()->SetSkill(skillId, 0, 0, 0); -} - diff --git a/src/server/game/Server/Protocol/Handlers/SpellHandler.cpp b/src/server/game/Server/Protocol/Handlers/SpellHandler.cpp deleted file mode 100755 index 09ba46654ee..00000000000 --- a/src/server/game/Server/Protocol/Handlers/SpellHandler.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/* - * 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 "DBCStores.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectMgr.h" -#include "GuildMgr.h" -#include "SpellMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Spell.h" -#include "Totem.h" -#include "TemporarySummon.h" -#include "SpellAuras.h" -#include "CreatureAI.h" -#include "ScriptMgr.h" -#include "GameObjectAI.h" -#include "SpellAuraEffects.h" - -void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets) -{ - // some spell cast packet including more data (for projectiles?) - if (castFlags & 0x02) - { - // not sure about these two - float elevation, speed; - recvPacket >> elevation; - recvPacket >> speed; - - targets.SetElevation(elevation); - targets.SetSpeed(speed); - - uint8 hasMovementData; - recvPacket >> hasMovementData; - if (hasMovementData) - { - recvPacket.rfinish(); - // movement packet for caster of the spell - /*recvPacket.read_skip<uint32>(); // MSG_MOVE_STOP - hardcoded in client - uint64 guid; - recvPacket.readPackGUID(guid); - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvPacket, &movementInfo);*/ - } - } -} - -void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) -{ - // TODO: add targets.read() check - Player* pUser = _player; - - // ignore for remote control state - if (pUser->m_mover != pUser) - return; - - uint8 bagIndex, slot, castFlags; - uint8 castCount; // next cast if exists (single or not) - uint64 itemGUID; - uint32 glyphIndex; // something to do with glyphs? - uint32 spellId; // casted spell id - - recvPacket >> bagIndex >> slot >> castCount >> spellId >> itemGUID >> glyphIndex >> castFlags; - - if (glyphIndex >= MAX_GLYPH_SLOT_INDEX) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - Item* pItem = pUser->GetUseableItemByPos(bagIndex, slot); - if (!pItem) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (pItem->GetGUID() != itemGUID) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - sLog->outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); - - ItemTemplate const* proto = pItem->GetTemplate(); - if (!proto) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); - return; - } - - // some item classes can be used only in equipped state - if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); - return; - } - - InventoryResult msg = pUser->CanUseItem(pItem); - if (msg != EQUIP_ERR_OK) - { - pUser->SendEquipError(msg, pItem, NULL); - return; - } - - // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) - if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && pUser->InArena()) - { - pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, NULL); - return; - } - - // don't allow items banned in arena - if (proto->Flags & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && pUser->InArena()) - { - pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, NULL); - return; - } - - if (pUser->isInCombat()) - { - for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId)) - { - if (!spellInfo->CanBeUsedInCombat()) - { - pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT, pItem, NULL); - return; - } - } - } - } - - // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) - if (pItem->GetTemplate()->Bonding == BIND_WHEN_USE || pItem->GetTemplate()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetTemplate()->Bonding == BIND_QUEST_ITEM) - { - if (!pItem->IsSoulBound()) - { - pItem->SetState(ITEM_CHANGED, pUser); - pItem->SetBinding(true); - } - } - - SpellCastTargets targets; - targets.Read(recvPacket, pUser); - HandleClientCastFlags(recvPacket, castFlags, targets); - - if (!pItem->IsTargetValidForItemUse(targets.GetUnitTarget())) - { - // free gray item after use fail - pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - - // send spell error - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) - { - // for implicit area/coord target spells - if (!targets.GetUnitTarget()) - Spell::SendCastResult(_player, spellInfo, castCount, SPELL_FAILED_NO_VALID_TARGETS); - // for explicit target spells - else - Spell::SendCastResult(_player, spellInfo, castCount, SPELL_FAILED_BAD_TARGETS); - } - return; - } - - // Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. - if (!sScriptMgr->OnItemUse(pUser, pItem, targets)) - { - // no script or script not process request by self - pUser->CastItemUseSpell(pItem, targets, castCount, glyphIndex); - } -} - -void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) -{ - sLog->outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); - - Player* pUser = _player; - - // ignore for remote control state - if (pUser->m_mover != pUser) - return; - - uint8 bagIndex, slot; - - recvPacket >> bagIndex >> slot; - - sLog->outDetail("bagIndex: %u, slot: %u", bagIndex, slot); - - Item* item = pUser->GetItemByPos(bagIndex, slot); - if (!item) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - ItemTemplate const* proto = item->GetTemplate(); - if (!proto) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL); - return; - } - - // Verify that the bag is an actual bag or wrapped item that can be used "normally" - if (!(proto->Flags & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) - { - pUser->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, item, NULL); - sLog->outError("Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!", - pUser->GetName(), pUser->GetGUIDLow(), item->GetGUIDLow(), proto->ItemId); - return; - } - - // locked item - uint32 lockId = proto->LockID; - if (lockId) - { - LockEntry const* lockInfo = sLockStore.LookupEntry(lockId); - - if (!lockInfo) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL); - sLog->outError("WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", item->GetGUIDLow(), lockId); - return; - } - - // was not unlocked yet - if (item->IsLocked()) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, item, NULL); - return; - } - } - - if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))// wrapped? - { - QueryResult result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", item->GetGUIDLow()); - if (result) - { - Field* fields = result->Fetch(); - uint32 entry = fields[0].GetUInt32(); - uint32 flags = fields[1].GetUInt32(); - - item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0); - item->SetEntry(entry); - item->SetUInt32Value(ITEM_FIELD_FLAGS, flags); - item->SetState(ITEM_CHANGED, pUser); - } - else - { - sLog->outError("Wrapped item %u don't have record in character_gifts table and will deleted", item->GetGUIDLow()); - pUser->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); - return; - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT); - - stmt->setUInt32(0, item->GetGUIDLow()); - - CharacterDatabase.Execute(stmt); - } - else - pUser->SendLoot(item->GetGUID(), LOOT_CORPSE); -} - -void WorldSession::HandleGameObjectUseOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); - - // ignore for remote control state - if (_player->m_mover != _player) - return; - - if (GameObject* obj = GetPlayer()->GetMap()->GetGameObject(guid)) - obj->Use(_player); -} - -void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) -{ - uint64 guid; - recvPacket >> guid; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid)); - - // ignore for remote control state - if (_player->m_mover != _player) - return; - - GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); - if (!go) - return; - - if (!go->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) - return; - - go->AI()->GossipHello(_player); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); -} - -void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) -{ - uint32 spellId, glyphIndex; - uint8 castCount, castFlags; - - recvPacket >> castCount; - recvPacket >> spellId; - recvPacket >> glyphIndex; - recvPacket >> castFlags; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size()); - - // ignore for remote control state (for player case) - Unit* mover = _player->m_mover; - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) - { - recvPacket.rfinish(); // prevent spam at ignore packet - return; - } - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - - if (!spellInfo) - { - sLog->outError("WORLD: unknown spell id %u", spellId); - recvPacket.rfinish(); // prevent spam at ignore packet - return; - } - - if (mover->GetTypeId() == TYPEID_PLAYER) - { - // not have spell in spellbook or spell passive and not casted by client - if (!mover->ToPlayer()->HasActiveSpell (spellId) || spellInfo->IsPassive()) - { - //cheater? kick? ban? - recvPacket.rfinish(); // prevent spam at ignore packet - return; - } - } - else - { - // not have spell in spellbook or spell passive and not casted by client - if ((mover->GetTypeId() == TYPEID_UNIT && !mover->ToCreature()->HasSpell(spellId)) || spellInfo->IsPassive()) - { - //cheater? kick? ban? - recvPacket.rfinish(); // prevent spam at ignore packet - return; - } - } - - // Client is resending autoshot cast opcode when other spell is casted during shoot rotation - // Skip it to prevent "interrupt" message - if (spellInfo->IsAutoRepeatRangedSpell() && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) - && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) - { - recvPacket.rfinish(); - return; - } - - // can't use our own spells when we're in possession of another unit, - if (_player->isPossessing()) - { - recvPacket.rfinish(); // prevent spam at ignore packet - return; - } - - // client provided targets - SpellCastTargets targets; - targets.Read(recvPacket, mover); - HandleClientCastFlags(recvPacket, castFlags, targets); - - // auto-selection buff level base at target level (in spellInfo) - if (targets.GetUnitTarget()) - { - SpellInfo const* actualSpellInfo = spellInfo->GetAuraRankForLevel(targets.GetUnitTarget()->getLevel()); - - // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message - if (actualSpellInfo) - spellInfo = actualSpellInfo; - } - - Spell* spell = new Spell(mover, spellInfo, TRIGGERED_NONE, 0, false); - spell->m_cast_count = castCount; // set count of casts - spell->m_glyphIndex = glyphIndex; - spell->prepare(&targets); -} - -void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) -{ - uint32 spellId; - - recvPacket.read_skip<uint8>(); // counter, increments with every CANCEL packet, don't use for now - recvPacket >> spellId; - - if (_player->IsNonMeleeSpellCasted(false)) - _player->InterruptNonMeleeSpells(false, spellId, false); -} - -void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) -{ - uint32 spellId; - recvPacket >> spellId; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - return; - - // not allow remove spells with attr SPELL_ATTR0_CANT_CANCEL - if (spellInfo->Attributes & SPELL_ATTR0_CANT_CANCEL) - return; - - // channeled spell case (it currently casted then) - if (spellInfo->IsChanneled()) - { - if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - if (curSpell->m_spellInfo->Id == spellId) - _player->InterruptSpell(CURRENT_CHANNELED_SPELL); - return; - } - - // non channeled case: - // don't allow remove non positive spells - // don't allow cancelling passive auras (some of them are visible) - if (!spellInfo->IsPositive() || spellInfo->IsPassive()) - return; - - // maybe should only remove one buff when there are multiple? - _player->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); -} - -void WorldSession::HandlePetCancelAuraOpcode(WorldPacket& recvPacket) -{ - uint64 guid; - uint32 spellId; - - recvPacket >> guid; - recvPacket >> spellId; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - sLog->outError("WORLD: unknown PET spell id %u", spellId); - return; - } - - Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!pet) - { - sLog->outError("HandlePetCancelAura: Attempt to cancel an aura for non-existant pet %u by player '%s'", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); - return; - } - - if (pet != GetPlayer()->GetGuardianPet() && pet != GetPlayer()->GetCharm()) - { - sLog->outError("HandlePetCancelAura: Pet %u is not a pet of player '%s'", uint32(GUID_LOPART(guid)), GetPlayer()->GetName()); - return; - } - - if (!pet->isAlive()) - { - pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); - return; - } - - pet->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); - - pet->AddCreatureSpellCooldown(spellId); -} - -void WorldSession::HandleCancelGrowthAuraOpcode(WorldPacket& /*recvPacket*/) -{ -} - -void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& /*recvPacket*/) -{ - // may be better send SMSG_CANCEL_AUTO_REPEAT? - // cancel and prepare for deleting - _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); -} - -void WorldSession::HandleCancelChanneling(WorldPacket & recv_data) -{ - recv_data.read_skip<uint32>(); // spellid, not used - - // ignore for remote control state (for player case) - Unit* mover = _player->m_mover; - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) - return; - - mover->InterruptSpell(CURRENT_CHANNELED_SPELL); -} - -void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket) -{ - // ignore for remote control state - if (_player->m_mover != _player) - return; - - uint8 slotId; - - recvPacket >> slotId; - - ++slotId; - if (slotId >= MAX_TOTEM_SLOT) - return; - - if (!_player->m_SummonSlot[slotId]) - return; - - Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_SummonSlot[slotId]); - // Don't unsummon sentry totem - if (totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY) - totem->ToTotem()->UnSummon(); -} - -void WorldSession::HandleSelfResOpcode(WorldPacket & /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SELF_RES"); // empty opcode - - if (_player->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) - return; // silent return, client should display error by itself and not send this opcode - - if (_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); - if (spellInfo) - _player->CastSpell(_player, spellInfo, false, 0); - - _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); - } -} - -void WorldSession::HandleSpellClick(WorldPacket& recv_data) -{ - uint64 guid; - recv_data >> guid; - - // this will get something not in world. crash - Creature* unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!unit) - return; - - // TODO: Unit::SetCharmedBy: 28782 is not in world but 0 is trying to charm it! -> crash - if (!unit->IsInWorld()) - return; - - unit->HandleSpellClick(_player); -} - -void WorldSession::HandleMirrorImageDataRequest(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GET_MIRRORIMAGE_DATA"); - uint64 guid; - recv_data >> guid; - - // Get unit for which data is needed by client - Unit* unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL); - if (!unit) - return; - - if (!unit->HasAuraType(SPELL_AURA_CLONE_CASTER)) - return; - - // Get creator of the unit (SPELL_AURA_CLONE_CASTER does not stack) - Unit* creator = unit->GetAuraEffectsByType(SPELL_AURA_CLONE_CASTER).front()->GetCaster(); - if (!creator) - return; - - WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68); - data << uint64(guid); - data << uint32(creator->GetDisplayId()); - data << uint8(creator->getRace()); - data << uint8(creator->getGender()); - data << uint8(creator->getClass()); - - if (creator->GetTypeId() == TYPEID_PLAYER) - { - Player* player = creator->ToPlayer(); - Guild* guild = NULL; - - if (uint32 guildId = player->GetGuildId()) - guild = sGuildMgr->GetGuildById(guildId); - - data << uint8(player->GetByteValue(PLAYER_BYTES, 0)); // skin - data << uint8(player->GetByteValue(PLAYER_BYTES, 1)); // face - data << uint8(player->GetByteValue(PLAYER_BYTES, 2)); // hair - data << uint8(player->GetByteValue(PLAYER_BYTES, 3)); // haircolor - data << uint8(player->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair - data << uint64(guild ? guild->GetGuid() : 0); - - static EquipmentSlots const itemSlots[] = - { - EQUIPMENT_SLOT_HEAD, - EQUIPMENT_SLOT_SHOULDERS, - EQUIPMENT_SLOT_BODY, - EQUIPMENT_SLOT_CHEST, - EQUIPMENT_SLOT_WAIST, - EQUIPMENT_SLOT_LEGS, - EQUIPMENT_SLOT_FEET, - EQUIPMENT_SLOT_WRISTS, - EQUIPMENT_SLOT_HANDS, - EQUIPMENT_SLOT_BACK, - EQUIPMENT_SLOT_TABARD, - EQUIPMENT_SLOT_END - }; - - // Display items in visible slots - for (EquipmentSlots const* itr = &itemSlots[0]; *itr != EQUIPMENT_SLOT_END; ++itr) - { - if (*itr == EQUIPMENT_SLOT_HEAD && player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) - data << uint32(0); - else if (*itr == EQUIPMENT_SLOT_BACK && player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) - data << uint32(0); - else if (Item const* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, *itr)) - data << uint32(item->GetTemplate()->DisplayInfoID); - else - data << uint32(0); - } - } - else - { - // Skip player data for creatures - data << uint8(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - } - - SendPacket(&data); -} - -void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_UPDATE_PROJECTILE_POSITION"); - - uint64 casterGuid; - uint32 spellId; - uint8 castCount; - float x, y, z; // Position of missile hit - - recvPacket.readPackGUID(casterGuid); - recvPacket >> spellId; - recvPacket >> castCount; - recvPacket >> x; - recvPacket >> y; - recvPacket >> z; - - WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21); - data << uint64(casterGuid); - data << uint8(castCount); - data << float(x); - data << float(y); - data << float(z); - SendPacket(&data); -} diff --git a/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp b/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp deleted file mode 100755 index 81481bdef31..00000000000 --- a/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "UpdateMask.h" -#include "Path.h" -#include "WaypointMovementGenerator.h" -#include "DestinationHolderImp.h" - -void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TAXINODE_STATUS_QUERY"); - - uint64 guid; - - recv_data >> guid; - SendTaxiStatus(guid); -} - -void WorldSession::SendTaxiStatus(uint64 guid) -{ - // cheating checks - Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WorldSession::SendTaxiStatus - Unit (GUID: %u) not found.", uint32(GUID_LOPART(guid))); - return; - } - - uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam()); - - // not found nearest - if (curloc == 0) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: current location %u ", curloc); - - WorldPacket data(SMSG_TAXINODE_STATUS, 9); - data << guid; - data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0); - SendPacket(&data); - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_TAXINODE_STATUS"); -} - -void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TAXIQUERYAVAILABLENODES"); - - uint64 guid; - recv_data >> guid; - - // cheating checks - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); - if (!unit) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTaxiQueryAvailableNodes - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // unknown taxi node case - if (SendLearnNewTaxiNode(unit)) - return; - - // known taxi node case - SendTaxiMenu(unit); -} - -void WorldSession::SendTaxiMenu(Creature* unit) -{ - // find current node - uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam()); - - if (curloc == 0) - return; - - bool lastTaxiCheaterState = GetPlayer()->isTaxiCheater(); - if (unit->GetEntry() == 29480) GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it. - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_TAXINODE_STATUS_QUERY %u ", curloc); - - WorldPacket data(SMSG_SHOWTAXINODES, (4+8+4+8*4)); - data << uint32(1); - data << uint64(unit->GetGUID()); - data << uint32(curloc); - GetPlayer()->m_taxi.AppendTaximaskTo(data, GetPlayer()->isTaxiCheater()); - SendPacket(&data); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_SHOWTAXINODES"); - - GetPlayer()->SetTaxiCheater(lastTaxiCheaterState); -} - -void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode) -{ - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) - GetPlayer()->GetMotionMaster()->MovementExpired(false); - - if (mountDisplayId) - GetPlayer()->Mount(mountDisplayId); - - GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path, pathNode); -} - -bool WorldSession::SendLearnNewTaxiNode(Creature* unit) -{ - // find current node - uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam()); - - if (curloc == 0) - return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result. - - if (GetPlayer()->m_taxi.SetTaximaskNode(curloc)) - { - WorldPacket msg(SMSG_NEW_TAXI_PATH, 0); - SendPacket(&msg); - - WorldPacket update(SMSG_TAXINODE_STATUS, 9); - update << uint64(unit->GetGUID()); - update << uint8(1); - SendPacket(&update); - - return true; - } - else - return false; -} - -void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid) -{ - if (GetPlayer()->m_taxi.SetTaximaskNode(nodeid)) - { - WorldPacket msg(SMSG_NEW_TAXI_PATH, 0); - SendPacket(&msg); - } -} - -void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); - - uint64 guid; - uint32 node_count; - - recv_data >> guid >> node_count; - - Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); - if (!npc) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleActivateTaxiExpressOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); - return; - } - std::vector<uint32> nodes; - - for (uint32 i = 0; i < node_count; ++i) - { - uint32 node; - recv_data >> node; - nodes.push_back(node); - } - - if (nodes.empty()) - return; - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d", nodes.front(), nodes.back()); - - GetPlayer()->ActivateTaxiPathTo(nodes, npc); -} - -void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_SPLINE_DONE"); - - uint64 guid; // used only for proper packet read - recv_data.readPackGUID(guid); - - MovementInfo movementInfo; // used only for proper packet read - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip<uint32>(); // unk - - // in taxi flight packet received in 2 case: - // 1) end taxi path in far (multi-node) flight - // 2) switch from one map to other in case multim-map taxi path - // we need process only (1) - - uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); - if (!curDest) - return; - - TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); - - // far teleport case - if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) - { - if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) - { - // short preparations to continue flight - FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - - flight->SetCurrentNodeAfterTeleport(); - TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; - flight->SkipCurrentNode(); - - GetPlayer()->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, GetPlayer()->GetOrientation()); - } - return; - } - - uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); - if (destinationnode > 0) // if more destinations to go - { - // current source node for next destination - uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); - - // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) - if (GetPlayer()->isTaxiCheater()) - { - if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) - { - WorldPacket data(SMSG_NEW_TAXI_PATH, 0); - _player->GetSession()->SendPacket(&data); - } - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); - - uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); - - uint32 path, cost; - sObjectMgr->GetTaxiPath(sourcenode, destinationnode, path, cost); - - if (path && mountDisplayId) - SendDoFlight(mountDisplayId, path, 1); // skip start fly node - else - GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next - return; - } - else - GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node - - GetPlayer()->CleanupAfterTaxiFlight(); - GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); - if (GetPlayer()->pvpInfo.inHostileArea) - GetPlayer()->CastSpell(GetPlayer(), 2479, true); -} - -void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXI"); - - uint64 guid; - std::vector<uint32> nodes; - nodes.resize(2); - - recv_data >> guid >> nodes[0] >> nodes[1]; - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_ACTIVATETAXI from %d to %d", nodes[0], nodes[1]); - Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); - if (!npc) - { - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleActivateTaxiOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); - return; - } - - GetPlayer()->ActivateTaxiPathTo(nodes, npc); -} diff --git a/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp b/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp deleted file mode 100755 index a270d42b000..00000000000 --- a/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * 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 "Language.h" -#include "WorldPacket.h" -#include "Common.h" -#include "ObjectMgr.h" -#include "TicketMgr.h" -#include "Player.h" -#include "World.h" -#include "WorldSession.h" -#include "Util.h" - -void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) -{ - // Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable) - if (sTicketMgr->GetStatus() == GMTICKET_QUEUE_STATUS_DISABLED) - return; - - if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_TICKET_REQ), sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ)); - return; - } - - GMTicketResponse response = GMTICKET_RESPONSE_FAILURE; - // Player must not have ticket - if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) - { - GmTicket* ticket = new GmTicket(GetPlayer(), recv_data); - sTicketMgr->AddTicket(ticket); - sTicketMgr->UpdateLastChange(); - - sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->GetId()); - - response = GMTICKET_RESPONSE_SUCCESS; - } - - WorldPacket data(SMSG_GMTICKET_CREATE, 4); - data << uint32(response); - SendPacket(&data); -} - -void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data) -{ - std::string message; - recv_data >> message; - - GMTicketResponse response = GMTICKET_RESPONSE_FAILURE; - if (GmTicket *ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) - { - SQLTransaction trans = SQLTransaction(NULL); - ticket->SetMessage(message); - ticket->SaveToDB(trans); - - sWorld->SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName(), ticket->GetId()); - - response = GMTICKET_RESPONSE_SUCCESS; - } - - WorldPacket data(SMSG_GMTICKET_UPDATETEXT, 4); - data << uint32(response); - SendPacket(&data); -} - -void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recv_data*/) -{ - if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) - { - WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); - data << uint32(GMTICKET_RESPONSE_TICKET_DELETED); - SendPacket(&data); - - sWorld->SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName(), ticket->GetId()); - - sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID()); - sTicketMgr->SendTicket(this, NULL); - } -} - -void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recv_data*/) -{ - SendQueryTimeResponse(); - - if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) - { - if (ticket->IsCompleted()) - ticket->SendResponse(this); - else - sTicketMgr->SendTicket(this, ticket); - } - else - sTicketMgr->SendTicket(this, NULL); -} - -void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recv_data*/) -{ - // Note: This only disables the ticket UI at client side and is not fully reliable - // are we sure this is a uint32? Should ask Zor - WorldPacket data(SMSG_GMTICKET_SYSTEMSTATUS, 4); - data << uint32(sTicketMgr->GetStatus() ? GMTICKET_QUEUE_STATUS_ENABLED : GMTICKET_QUEUE_STATUS_DISABLED); - SendPacket(&data); -} - -void WorldSession::HandleGMSurveySubmit(WorldPacket& recv_data) -{ - uint32 nextSurveyID = sTicketMgr->GetNextSurveyID(); - // just put the survey into the database - uint32 mainSurvey; // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc - recv_data >> mainSurvey; - - // sub_survey1, r1, comment1, sub_survey2, r2, comment2, sub_survey3, r3, comment3, sub_survey4, r4, comment4, sub_survey5, r5, comment5, sub_survey6, r6, comment6, sub_survey7, r7, comment7, sub_survey8, r8, comment8, sub_survey9, r9, comment9, sub_survey10, r10, comment10, - for (uint8 i = 0; i < 10; i++) - { - uint32 subSurveyId; // ref to i'th GMSurveySurveys.dbc field (all fields in that dbc point to fields in GMSurveyQuestions.dbc) - recv_data >> subSurveyId; - if (!subSurveyId) - break; - - uint8 rank; // probably some sort of ref to GMSurveyAnswers.dbc - recv_data >> rank; - std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)") - recv_data >> comment; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SUBSURVEY); - stmt->setUInt32(0, nextSurveyID); - stmt->setUInt32(1, subSurveyId); - stmt->setUInt32(2, rank); - stmt->setString(3, comment); - CharacterDatabase.Execute(stmt); - } - - std::string comment; // just a guess - recv_data >> comment; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SURVEY); - stmt->setUInt32(0, GUID_LOPART(GetPlayer()->GetGUID())); - stmt->setUInt32(1, nextSurveyID); - stmt->setUInt32(2, mainSurvey); - stmt->setString(3, comment); - - CharacterDatabase.Execute(stmt); -} - -void WorldSession::HandleReportLag(WorldPacket& recv_data) -{ - // just put the lag report into the database... - // can't think of anything else to do with it - uint32 lagType, mapId; - recv_data >> lagType; - recv_data >> mapId; - float x, y, z; - recv_data >> x; - recv_data >> y; - recv_data >> z; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LAG_REPORT); - stmt->setUInt32(0, GUID_LOPART(GetPlayer()->GetGUID())); - stmt->setUInt8 (1, lagType); - stmt->setUInt16(2, mapId); - stmt->setFloat (3, x); - stmt->setFloat (4, y); - stmt->setFloat (5, z); - CharacterDatabase.Execute(stmt); -} - -void WorldSession::HandleGMResponseResolve(WorldPacket& /*recvPacket*/) -{ - // empty packet - if (GmTicket* ticket = sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID())) - { - uint8 getSurvey = 0; - if (float(rand_chance()) < sWorld->getFloatConfig(CONFIG_CHANCE_OF_GM_SURVEY)) - getSurvey = 1; - - WorldPacket data(SMSG_GMRESPONSE_STATUS_UPDATE, 4); - data << uint8(getSurvey); - SendPacket(&data); - - WorldPacket data2(SMSG_GMTICKET_DELETETICKET, 4); - data2 << uint32(GMTICKET_RESPONSE_TICKET_DELETED); - SendPacket(&data2); - - sTicketMgr->CloseTicket(ticket->GetId(), GetPlayer()->GetGUID()); - sTicketMgr->SendTicket(this, NULL); - } -} diff --git a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp deleted file mode 100755 index 900f036df0a..00000000000 --- a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp +++ /dev/null @@ -1,751 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectAccessor.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" -#include "Item.h" -#include "Spell.h" -#include "SocialMgr.h" -#include "Language.h" -#include "AccountMgr.h" - -void WorldSession::SendTradeStatus(TradeStatus status) -{ - WorldPacket data; - - switch (status) - { - case TRADE_STATUS_BEGIN_TRADE: - data.Initialize(SMSG_TRADE_STATUS, 4+8); - data << uint32(status); - data << uint64(0); - break; - case TRADE_STATUS_OPEN_WINDOW: - data.Initialize(SMSG_TRADE_STATUS, 4+4); - data << uint32(status); - data << uint32(0); // added in 2.4.0 - break; - case TRADE_STATUS_CLOSE_WINDOW: - data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4); - data << uint32(status); - data << uint32(0); - data << uint8(0); - data << uint32(0); - break; - case TRADE_STATUS_ONLY_CONJURED: - case TRADE_STATUS_NOT_ELIGIBLE: - data.Initialize(SMSG_TRADE_STATUS, 4+1); - data << uint32(status); - data << uint8(0); - break; - default: - data.Initialize(SMSG_TRADE_STATUS, 4); - data << uint32(status); - break; - } - - SendPacket(&data); -} - -void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Ignore Trade %u", _player->GetGUIDLow()); - // recvPacket.print_storage(); -} - -void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Busy Trade %u", _player->GetGUIDLow()); - // recvPacket.print_storage(); -} - -void WorldSession::SendUpdateTrade(bool trader_data /*= true*/) -{ - TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData(); - - WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 1+4+4+4+4+4+7*(1+4+4+4+4+8+4+4+4+4+8+4+4+4+4+4+4)); - data << uint8(trader_data); // 1 means traders data, 0 means own - data << uint32(0); // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?) - data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases - data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases - data << uint32(view_trade->GetMoney()); // trader gold - data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item - - for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) - { - data << uint8(i); // trade slot number, if not specified, then end of packet - - if (Item* item = view_trade->GetItem(TradeSlots(i))) - { - data << uint32(item->GetTemplate()->ItemId); // entry - data << uint32(item->GetTemplate()->DisplayInfoID);// display id - data << uint32(item->GetCount()); // stack count - // wrapped: hide stats but show giftcreator name - data << uint32(item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED) ? 1 : 0); - data << uint64(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)); - // perm. enchantment and gems - data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)); - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) - data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); - // creator - data << uint64(item->GetUInt64Value(ITEM_FIELD_CREATOR)); - data << uint32(item->GetSpellCharges()); // charges - data << uint32(item->GetItemSuffixFactor()); // SuffixFactor - data << uint32(item->GetItemRandomPropertyId());// random properties id - data << uint32(item->GetTemplate()->LockID); // lock id - // max durability - data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); - // durability - data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY)); - } - else - { - for (uint8 j = 0; j < 18; ++j) - data << uint32(0); - } - } - SendPacket(&data); -} - -//============================================================== -// transfer the items to the players - -void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) -{ - Player* trader = _player->GetTrader(); - if (!trader) - return; - - for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i) - { - ItemPosCountVec traderDst; - ItemPosCountVec playerDst; - bool traderCanTrade = (myItems[i] == NULL || trader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, myItems[i], false) == EQUIP_ERR_OK); - bool playerCanTrade = (hisItems[i] == NULL || _player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, hisItems[i], false) == EQUIP_ERR_OK); - if (traderCanTrade && playerCanTrade) - { - // Ok, if trade item exists and can be stored - // If we trade in both directions we had to check, if the trade will work before we actually do it - // A roll back is not possible after we stored it - if (myItems[i]) - { - // logging - sLog->outDebug(LOG_FILTER_NETWORKIO, "partner storing: %u", myItems[i]->GetGUIDLow()); - if (!AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", - _player->GetName(), _player->GetSession()->GetAccountId(), - myItems[i]->GetTemplate()->Name1.c_str(), myItems[i]->GetEntry(), myItems[i]->GetCount(), - trader->GetName(), trader->GetSession()->GetAccountId()); - } - - // adjust time (depends on /played) - if (myItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) - myItems[i]->SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, trader->GetTotalPlayedTime()-(_player->GetTotalPlayedTime()-myItems[i]->GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME))); - // store - trader->MoveItemToInventory(traderDst, myItems[i], true, true); - } - if (hisItems[i]) - { - // logging - sLog->outDebug(LOG_FILTER_NETWORKIO, "player storing: %u", hisItems[i]->GetGUIDLow()); - if (!AccountMgr::IsPlayerAccount(trader->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", - trader->GetName(), trader->GetSession()->GetAccountId(), - hisItems[i]->GetTemplate()->Name1.c_str(), hisItems[i]->GetEntry(), hisItems[i]->GetCount(), - _player->GetName(), _player->GetSession()->GetAccountId()); - } - - // adjust time (depends on /played) - if (hisItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) - hisItems[i]->SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, _player->GetTotalPlayedTime()-(trader->GetTotalPlayedTime()-hisItems[i]->GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME))); - // store - _player->MoveItemToInventory(playerDst, hisItems[i], true, true); - } - } - else - { - // in case of fatal error log error message - // return the already removed items to the original owner - if (myItems[i]) - { - if (!traderCanTrade) - sLog->outError("trader can't store item: %u", myItems[i]->GetGUIDLow()); - if (_player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, myItems[i], false) == EQUIP_ERR_OK) - _player->MoveItemToInventory(playerDst, myItems[i], true, true); - else - sLog->outError("player can't take item back: %u", myItems[i]->GetGUIDLow()); - } - // return the already removed items to the original owner - if (hisItems[i]) - { - if (!playerCanTrade) - sLog->outError("player can't store item: %u", hisItems[i]->GetGUIDLow()); - if (trader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK) - trader->MoveItemToInventory(traderDst, hisItems[i], true, true); - else - sLog->outError("trader can't take item back: %u", hisItems[i]->GetGUIDLow()); - } - } - } -} - -//============================================================== - -static void setAcceptTradeMode(TradeData* myTrade, TradeData* hisTrade, Item* *myItems, Item* *hisItems) -{ - myTrade->SetInAcceptProcess(true); - hisTrade->SetInAcceptProcess(true); - - // store items in local list and set 'in-trade' flag - for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i) - { - if (Item* item = myTrade->GetItem(TradeSlots(i))) - { - sLog->outStaticDebug("player trade item %u bag: %u slot: %u", item->GetGUIDLow(), item->GetBagSlot(), item->GetSlot()); - //Can return NULL - myItems[i] = item; - myItems[i]->SetInTrade(); - } - - if (Item* item = hisTrade->GetItem(TradeSlots(i))) - { - sLog->outStaticDebug("partner trade item %u bag: %u slot: %u", item->GetGUIDLow(), item->GetBagSlot(), item->GetSlot()); - hisItems[i] = item; - hisItems[i]->SetInTrade(); - } - } -} - -static void clearAcceptTradeMode(TradeData* myTrade, TradeData* hisTrade) -{ - myTrade->SetInAcceptProcess(false); - hisTrade->SetInAcceptProcess(false); -} - -static void clearAcceptTradeMode(Item* *myItems, Item* *hisItems) -{ - // clear 'in-trade' flag - for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i) - { - if (myItems[i]) - myItems[i]->SetInTrade(false); - if (hisItems[i]) - hisItems[i]->SetInTrade(false); - } -} - -void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) -{ - TradeData* my_trade = _player->m_trade; - if (!my_trade) - return; - - Player* trader = my_trade->GetTrader(); - - TradeData* his_trade = trader->m_trade; - if (!his_trade) - return; - - Item* myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; - Item* hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; - bool myCanCompleteTrade = true, hisCanCompleteTrade = true; - - // set before checks for propertly undo at problems (it already set in to client) - my_trade->SetAccepted(true); - - // not accept case incorrect money amount - if (!_player->HasEnoughMoney(my_trade->GetMoney())) - { - SendNotification(LANG_NOT_ENOUGH_GOLD); - my_trade->SetAccepted(false, true); - return; - } - - // not accept case incorrect money amount - if (!trader->HasEnoughMoney(his_trade->GetMoney())) - { - trader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD); - his_trade->SetAccepted(false, true); - return; - } - - // not accept if some items now can't be trade (cheating) - for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i) - { - if (Item* item = my_trade->GetItem(TradeSlots(i))) - { - if (!item->CanBeTraded(false, true)) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - if (item->IsBindedNotWith(trader)) - { - SendTradeStatus(TRADE_STATUS_NOT_ELIGIBLE); - SendTradeStatus(TRADE_STATUS_CLOSE_WINDOW/*TRADE_STATUS_TRADE_CANCELED*/); - return; - } - } - - if (Item* item = his_trade->GetItem(TradeSlots(i))) - { - if (!item->CanBeTraded(false, true)) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - //if (item->IsBindedNotWith(_player)) // dont mark as invalid when his item isnt good (not exploitable because if item is invalid trade will fail anyway later on the same check) - //{ - // SendTradeStatus(TRADE_STATUS_NOT_ELIGIBLE); - // his_trade->SetAccepted(false, true); - // return; - //} - } - } - - if (his_trade->IsAccepted()) - { - setAcceptTradeMode(my_trade, his_trade, myItems, hisItems); - - Spell* my_spell = NULL; - SpellCastTargets my_targets; - - Spell* his_spell = NULL; - SpellCastTargets his_targets; - - // not accept if spell can't be casted now (cheating) - if (uint32 my_spell_id = my_trade->GetSpell()) - { - SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(my_spell_id); - Item* castItem = my_trade->GetSpellCastItem(); - - if (!spellEntry || !his_trade->GetItem(TRADE_SLOT_NONTRADED) || - (my_trade->HasSpellCastItem() && !castItem)) - { - clearAcceptTradeMode(my_trade, his_trade); - clearAcceptTradeMode(myItems, hisItems); - - my_trade->SetSpell(0); - return; - } - - my_spell = new Spell(_player, spellEntry, TRIGGERED_FULL_MASK); - my_spell->m_CastItem = castItem; - my_targets.SetTradeItemTarget(_player); - my_spell->m_targets = my_targets; - - SpellCastResult res = my_spell->CheckCast(true); - if (res != SPELL_CAST_OK) - { - my_spell->SendCastResult(res); - - clearAcceptTradeMode(my_trade, his_trade); - clearAcceptTradeMode(myItems, hisItems); - - delete my_spell; - my_trade->SetSpell(0); - return; - } - } - - // not accept if spell can't be casted now (cheating) - if (uint32 his_spell_id = his_trade->GetSpell()) - { - SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(his_spell_id); - Item* castItem = his_trade->GetSpellCastItem(); - - if (!spellEntry || !my_trade->GetItem(TRADE_SLOT_NONTRADED) || (his_trade->HasSpellCastItem() && !castItem)) - { - delete my_spell; - his_trade->SetSpell(0); - - clearAcceptTradeMode(my_trade, his_trade); - clearAcceptTradeMode(myItems, hisItems); - return; - } - - his_spell = new Spell(trader, spellEntry, TRIGGERED_FULL_MASK); - his_spell->m_CastItem = castItem; - his_targets.SetTradeItemTarget(trader); - his_spell->m_targets = his_targets; - - SpellCastResult res = his_spell->CheckCast(true); - if (res != SPELL_CAST_OK) - { - his_spell->SendCastResult(res); - - clearAcceptTradeMode(my_trade, his_trade); - clearAcceptTradeMode(myItems, hisItems); - - delete my_spell; - delete his_spell; - - his_trade->SetSpell(0); - return; - } - } - - // inform partner client - trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); - - // test if item will fit in each inventory - hisCanCompleteTrade = (trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); - myCanCompleteTrade = (_player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); - - clearAcceptTradeMode(myItems, hisItems); - - // in case of missing space report error - if (!myCanCompleteTrade) - { - clearAcceptTradeMode(my_trade, his_trade); - - SendNotification(LANG_NOT_FREE_TRADE_SLOTS); - trader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); - my_trade->SetAccepted(false); - his_trade->SetAccepted(false); - return; - } - else if (!hisCanCompleteTrade) - { - clearAcceptTradeMode(my_trade, his_trade); - - SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); - trader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS); - my_trade->SetAccepted(false); - his_trade->SetAccepted(false); - return; - } - - // execute trade: 1. remove - for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i) - { - if (myItems[i]) - { - myItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); - _player->MoveItemFromInventory(myItems[i]->GetBagSlot(), myItems[i]->GetSlot(), true); - } - if (hisItems[i]) - { - hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, trader->GetGUID()); - trader->MoveItemFromInventory(hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot(), true); - } - } - - // execute trade: 2. store - moveItems(myItems, hisItems); - - // logging money - if (sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) - { - if (!AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()) && my_trade->GetMoney() > 0) - { - sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", - _player->GetName(), _player->GetSession()->GetAccountId(), - my_trade->GetMoney(), - trader->GetName(), trader->GetSession()->GetAccountId()); - } - if (!AccountMgr::IsPlayerAccount(trader->GetSession()->GetSecurity()) && his_trade->GetMoney() > 0) - { - sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", - trader->GetName(), trader->GetSession()->GetAccountId(), - his_trade->GetMoney(), - _player->GetName(), _player->GetSession()->GetAccountId()); - } - } - - // update money - _player->ModifyMoney(-int32(my_trade->GetMoney())); - _player->ModifyMoney(his_trade->GetMoney()); - trader->ModifyMoney(-int32(his_trade->GetMoney())); - trader->ModifyMoney(my_trade->GetMoney()); - - if (my_spell) - my_spell->prepare(&my_targets); - - if (his_spell) - his_spell->prepare(&his_targets); - - // cleanup - clearAcceptTradeMode(my_trade, his_trade); - delete _player->m_trade; - _player->m_trade = NULL; - delete trader->m_trade; - trader->m_trade = NULL; - - // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - _player->SaveInventoryAndGoldToDB(trans); - trader->SaveInventoryAndGoldToDB(trans); - CharacterDatabase.CommitTransaction(trans); - - trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); - SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); - } - else - { - trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); - } -} - -void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/) -{ - TradeData* my_trade = _player->GetTradeData(); - if (!my_trade) - return; - - my_trade->SetAccepted(false, true); -} - -void WorldSession::HandleBeginTradeOpcode(WorldPacket& recvPacket) -{ -/* - TODO: Need to verify - - BitStream mask = recvPacket.ReadBitStream(8); - - ByteBuffer bytes(8, true); - - recvPacket.ReadXorByte(mask[0], bytes[5]); - recvPacket.ReadXorByte(mask[4], bytes[2]); - recvPacket.ReadXorByte(mask[5], bytes[3]); - recvPacket.ReadXorByte(mask[2], bytes[4]); - recvPacket.ReadXorByte(mask[7], bytes[1]); - recvPacket.ReadXorByte(mask[3], bytes[0]); - recvPacket.ReadXorByte(mask[1], bytes[6]); - recvPacket.ReadXorByte(mask[6], bytes[7]); - - uint64 tradeGuid = BitConverter::ToUInt64(bytes); -*/ - recvPacket.rfinish(); - - TradeData* my_trade = _player->m_trade; - if (!my_trade) - return; - - my_trade->GetTrader()->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); - SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); -} - -void WorldSession::SendCancelTrade() -{ - if (m_playerRecentlyLogout) - return; - - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); -} - -void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/) -{ - // sended also after LOGOUT COMPLETE - if (_player) // needed because STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT - _player->TradeCancel(true); -} - -void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) -{ - if (GetPlayer()->m_trade) - { - recvPacket.rfinish(); - return; - } - - uint64 ID; - recvPacket >> ID; - - if (!GetPlayer()->isAlive()) - { - SendTradeStatus(TRADE_STATUS_YOU_DEAD); - return; - } - - if (GetPlayer()->HasUnitState(UNIT_STAT_STUNNED)) - { - SendTradeStatus(TRADE_STATUS_YOU_STUNNED); - return; - } - - if (isLogingOut()) - { - SendTradeStatus(TRADE_STATUS_YOU_LOGOUT); - return; - } - - if (GetPlayer()->isInFlight()) - { - SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); - return; - } - - if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_TRADE_REQ), sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)); - return; - } - - Player* pOther = ObjectAccessor::FindPlayer(ID); - - if (!pOther) - { - SendTradeStatus(TRADE_STATUS_NO_TARGET); - return; - } - - if (pOther == GetPlayer() || pOther->m_trade) - { - SendTradeStatus(TRADE_STATUS_BUSY); - return; - } - - if (!pOther->isAlive()) - { - SendTradeStatus(TRADE_STATUS_TARGET_DEAD); - return; - } - - if (pOther->isInFlight()) - { - SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); - return; - } - - if (pOther->HasUnitState(UNIT_STAT_STUNNED)) - { - SendTradeStatus(TRADE_STATUS_TARGET_STUNNED); - return; - } - - if (pOther->GetSession()->isLogingOut()) - { - SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT); - return; - } - - if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - { - SendTradeStatus(TRADE_STATUS_IGNORE_YOU); - return; - } - - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam()) - { - SendTradeStatus(TRADE_STATUS_WRONG_FACTION); - return; - } - - if (!pOther->IsWithinDistInMap(_player, 10.0f, false)) - { - SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); - return; - } - - if (pOther->getLevel() < sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_TRADE_OTHER_REQ), sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)); - return; - } - - // OK start trade - _player->m_trade = new TradeData(_player, pOther); - pOther->m_trade = new TradeData(pOther, _player); - - WorldPacket data(SMSG_TRADE_STATUS, 12); - data << uint32(TRADE_STATUS_BEGIN_TRADE); - data << uint64(_player->GetGUID()); - pOther->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket) -{ - uint32 gold; - recvPacket >> gold; - - TradeData* my_trade = _player->GetTradeData(); - if (!my_trade) - return; - - // gold can be incorrect, but this is checked at trade finished. - my_trade->SetMoney(gold); -} - -void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) -{ - // send update - uint8 tradeSlot; - uint8 bag; - uint8 slot; - - recvPacket >> tradeSlot; - recvPacket >> bag; - recvPacket >> slot; - - TradeData* my_trade = _player->GetTradeData(); - if (!my_trade) - return; - - // invalid slot number - if (tradeSlot >= TRADE_SLOT_COUNT) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - - // check cheating, can't fail with correct client operations - Item* item = _player->GetItemByPos(bag, slot); - if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded(false, true))) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - - uint64 iGUID = item->GetGUID(); - - // prevent place single item into many trade slots using cheating and client bugs - if (my_trade->HasItem(iGUID)) - { - // cheating attempt - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - - my_trade->SetItem(TradeSlots(tradeSlot), item); -} - -void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket) -{ - uint8 tradeSlot; - recvPacket >> tradeSlot; - - TradeData* my_trade = _player->m_trade; - if (!my_trade) - return; - - // invalid slot number - if (tradeSlot >= TRADE_SLOT_COUNT) - return; - - my_trade->SetItem(TradeSlots(tradeSlot), NULL); -} - diff --git a/src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp b/src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp deleted file mode 100644 index ce4f6ccb8fe..00000000000 --- a/src/server/game/Server/Protocol/Handlers/VehicleHandler.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Vehicle.h" -#include "Player.h" -#include "Log.h" -#include "ObjectAccessor.h" - -void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); - - uint64 vehicleGUID = _player->GetCharmGUID(); - - if (!vehicleGUID) // something wrong here... - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - uint64 guid; - - recv_data.readPackGUID(guid); - - MovementInfo mi; - mi.guid = guid; - ReadMovementInfo(recv_data, &mi); - - _player->m_movementInfo = mi; - - _player->ExitVehicle(); -} - -void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); - - Unit* vehicle_base = GetPlayer()->GetVehicleBase(); - if (!vehicle_base) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - - VehicleSeatEntry const* seat = GetPlayer()->GetVehicle()->GetSeatForPassenger(GetPlayer()); - if (!seat->CanSwitchFromSeat()) - { - recv_data.rfinish(); // prevent warnings spam - sLog->outError("HandleChangeSeatsOnControlledVehicle, Opcode: %u, Player %u tried to switch seats but current seatflags %u don't permit that.", - recv_data.GetOpcode(), GetPlayer()->GetGUIDLow(), seat->m_flags); - return; - } - - switch (recv_data.GetOpcode()) - { - case CMSG_REQUEST_VEHICLE_PREV_SEAT: - GetPlayer()->ChangeSeat(-1, false); - break; - case CMSG_REQUEST_VEHICLE_NEXT_SEAT: - GetPlayer()->ChangeSeat(-1, true); - break; - case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: - { - uint64 guid; // current vehicle guid - recv_data.readPackGUID(guid); - - ReadMovementInfo(recv_data, &vehicle_base->m_movementInfo); - - uint64 accessory; // accessory guid - recv_data.readPackGUID(accessory); - - int8 seatId; - recv_data >> seatId; - - if (vehicle_base->GetGUID() != guid) - return; - - if (!accessory) - GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next - else if (Unit* vehUnit = Unit::GetUnit(*GetPlayer(), accessory)) - { - if (Vehicle* vehicle = vehUnit->GetVehicleKit()) - if (vehicle->HasEmptySeat(seatId)) - vehUnit->HandleSpellClick(GetPlayer(), seatId); - } - break; - } - case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: - { - uint64 guid; // current vehicle guid - recv_data.readPackGUID(guid); - - int8 seatId; - recv_data >> seatId; - - if (vehicle_base->GetGUID() == guid) - GetPlayer()->ChangeSeat(seatId); - else if (Unit* vehUnit = Unit::GetUnit(*GetPlayer(), guid)) - if (Vehicle* vehicle = vehUnit->GetVehicleKit()) - if (vehicle->HasEmptySeat(seatId)) - vehUnit->HandleSpellClick(GetPlayer(), seatId); - break; - } - default: - break; - } -} - -void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data) -{ - // Read guid - uint64 guid; - data >> guid; - - if (Player* player = ObjectAccessor::FindPlayer(guid)) - { - if (!player->GetVehicleKit()) - return; - if (!player->IsInRaidWith(_player)) - return; - if (!player->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) - return; - - _player->EnterVehicle(player); - } -} - -void WorldSession::HandleEjectPassenger(WorldPacket &data) -{ - Vehicle* vehicle = _player->GetVehicleKit(); - if (!vehicle) - { - data.rfinish(); // prevent warnings spam - sLog->outError("HandleEjectPassenger: Player %u is not in a vehicle!", GetPlayer()->GetGUIDLow()); - return; - } - - uint64 guid; - data >> guid; - - if (IS_PLAYER_GUID(guid)) - { - Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) - { - sLog->outError("Player %u tried to eject player %u from vehicle, but the latter was not found in world!", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid)); - return; - } - - if (!player->IsOnVehicle(vehicle->GetBase())) - { - sLog->outError("Player %u tried to eject player %u, but they are not in the same vehicle", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid)); - return; - } - - VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(player); - ASSERT(seat); - if (seat->IsEjectable()) - player->ExitVehicle(); - else - sLog->outError("Player %u attempted to eject player %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid)); - } - - else if (IS_CREATURE_GUID(guid)) - { - Unit* unit = ObjectAccessor::GetUnit(*_player, guid); - if (!unit) // creatures can be ejected too from player mounts - { - sLog->outError("Player %u tried to eject creature guid %u from vehicle, but the latter was not found in world!", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid)); - return; - } - - if (!unit->IsOnVehicle(vehicle->GetBase())) - { - sLog->outError("Player %u tried to eject unit %u, but they are not in the same vehicle", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid)); - return; - } - - VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(unit); - ASSERT(seat); - if (seat->IsEjectable()) - { - ASSERT(GetPlayer() == vehicle->GetBase()); - unit->ExitVehicle(); - } - else - sLog->outError("Player %u attempted to eject creature GUID %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid)); - } - else - sLog->outError("HandleEjectPassenger: Player %u tried to eject invalid GUID "UI64FMTD, GetPlayer()->GetGUIDLow(), guid); -} - -void WorldSession::HandleRequestVehicleExit(WorldPacket& /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT"); - - if (Vehicle* vehicle = GetPlayer()->GetVehicle()) - { - if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(GetPlayer())) - { - if (seat->CanEnterOrExit()) - GetPlayer()->ExitVehicle(); - else - sLog->outError("Player %u tried to exit vehicle, but seatflags %u (ID: %u) don't permit that.", - GetPlayer()->GetGUIDLow(), seat->m_ID, seat->m_flags); - } - } -} diff --git a/src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp b/src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp deleted file mode 100755 index 34ad5ac3eae..00000000000 --- a/src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" - -void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_VOICE_SESSION_ENABLE"); - // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled - recv_data.read_skip<uint8>(); - recv_data.read_skip<uint8>(); -} - -void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket& /*recv_data*/) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CHANNEL_VOICE_ON"); - // Enable Voice button in channel context menu -} - -void WorldSession::HandleSetActiveVoiceChannel(WorldPacket& recv_data) -{ - sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SET_ACTIVE_VOICE_CHANNEL"); - recv_data.read_skip<uint32>(); - recv_data.read_skip<char*>(); -} - diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 84ccc3e574b..978f33c88aa 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -96,7 +96,7 @@ m_playerRecentlyLogout(false), m_playerSave(false), m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(locale), m_latency(0), m_TutorialsChanged(false), recruiterId(recruiter), -isRecruiter(isARecruiter) +isRecruiter(isARecruiter), timeLastWhoCommand(0) { if (sock) { diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index ff07164e7b2..d4cf3119257 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -964,6 +964,7 @@ class WorldSession uint32 recruiterId; bool isRecruiter; ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue; + time_t timeLastWhoCommand; }; #endif /// @} |
