Advertisement
Guest User

MiscHandler.cpp

a guest
Sep 24th, 2016
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 66.34 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
  3.  * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2 of the License, or (at your
  8.  * option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful, but WITHOUT
  11.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12.  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13.  * more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program. If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include "Common.h"
  20. #include "Language.h"
  21. #include "DatabaseEnv.h"
  22. #include "WorldPacket.h"
  23. #include "Opcodes.h"
  24. #include "Log.h"
  25. #include "Player.h"
  26. #include "GossipDef.h"
  27. #include "World.h"
  28. #include "ObjectMgr.h"
  29. #include "GuildMgr.h"
  30. #include "WorldSession.h"
  31. #include "Chat.h"
  32. #include "zlib.h"
  33. #include "ObjectAccessor.h"
  34. #include "Object.h"
  35. #include "Battleground.h"
  36. #include "OutdoorPvP.h"
  37. #include "SocialMgr.h"
  38. #include "AccountMgr.h"
  39. #include "DBCEnums.h"
  40. #include "ScriptMgr.h"
  41. #include "MapManager.h"
  42. #include "GameObjectAI.h"
  43. #include "Group.h"
  44. #include "Spell.h"
  45. #include "BattlegroundMgr.h"
  46. #include "Battlefield.h"
  47. #include "BattlefieldMgr.h"
  48. #ifdef ELUNA
  49. #include "LuaEngine.h"
  50. #endif
  51.  
  52. void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
  53. {
  54.     TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_REPOP_REQUEST Message");
  55.  
  56.     recvData.read_skip<uint8>();
  57.  
  58.     if (GetPlayer()->IsAlive() || GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
  59.         return;
  60.  
  61.     if (GetPlayer()->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
  62.         return; // silently return, client should display the error by itself
  63.  
  64.     // the world update order is sessions, players, creatures
  65.     // the netcode runs in parallel with all of these
  66.     // creatures can kill players
  67.     // so if the server is lagging enough the player can
  68.     // release spirit after he's killed but before he is updated
  69.    if (GetPlayer()->getDeathState() == JUST_DIED)
  70.    {
  71.        TC_LOG_DEBUG("network", "HandleRepopRequestOpcode: got request after player %s(%d) was killed and before he was updated",
  72.            GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
  73.        GetPlayer()->KillPlayer();
  74.    }
  75.  
  76. #ifdef ELUNA
  77.    sEluna->OnRepop(GetPlayer());
  78. #endif
  79.  
  80.    //this is spirit release confirm?
  81.    GetPlayer()->RemoveGhoul();
  82.    GetPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
  83.    GetPlayer()->BuildPlayerRepop();
  84.    GetPlayer()->RepopAtGraveyard();
  85. }
  86.  
  87. void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recvData)
  88. {
  89.    TC_LOG_DEBUG("network", "WORLD: CMSG_GOSSIP_SELECT_OPTION");
  90.  
  91.    uint32 gossipListId;
  92.    uint32 menuId;
  93.    ObjectGuid guid;
  94.    std::string code = "";
  95.  
  96.    recvData >> guid >> menuId >> gossipListId;
  97.  
  98.    if (!_player->PlayerTalkClass->GetGossipMenu().GetItem(gossipListId))
  99.    {
  100.        recvData.rfinish();
  101.        return;
  102.    }
  103.  
  104.    if (_player->PlayerTalkClass->IsGossipOptionCoded(gossipListId))
  105.        recvData >> code;
  106.  
  107.    // Prevent cheating on C++ scripted menus
  108.    if (_player->PlayerTalkClass->GetGossipMenu().GetSenderGUID() != guid)
  109.        return;
  110.    
  111.  
  112. #ifdef ELUNA
  113.    Item* item = NULL;
  114. #endif
  115.    Creature* unit = NULL;
  116.    GameObject* go = NULL;
  117.    if (guid.IsCreatureOrVehicle())
  118.    {
  119.        unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_GOSSIP);
  120.        if (!unit)
  121.        {
  122.            TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found or you can't interact with him.", guid.ToString().c_str());
  123.            return;
  124.        }
  125.    }
  126.    else if (guid.IsGameObject())
  127.    {
  128.        go = _player->GetGameObjectIfCanInteractWith(guid);
  129.        if (!go)
  130.        {
  131.            TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found or you can't interact with it.", guid.ToString().c_str());
  132.            return;
  133.        }
  134.    }
  135. #ifdef ELUNA
  136.    else if (guid.IsItem())
  137.    {
  138.        item = _player->GetItemByGuid(guid);
  139.        if (!item)
  140.        {
  141.            TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", guid.ToString().c_str());
  142.            return;
  143.        }
  144.    }
  145.    else if (guid.IsPlayer())
  146.    {
  147.        if (_player->GetGUID() != guid)
  148.        {
  149.            TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", guid.ToString().c_str());
  150.            return;
  151.        }
  152.    }
  153. #endif
  154.    else if (guid.IsItem())
  155.    {
  156.        item = _player->GetItemByGuid(guid);
  157.        if (!item || _player->IsBankPos(item->GetPos()))
  158.        {
  159.            TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", guid.ToString().c_str());
  160.            return;
  161.        }
  162.    }
  163.    else if (guid.IsPlayer())
  164.    {
  165.        if (guid != _player->GetGUID() || menuId != _player->PlayerTalkClass->GetGossipMenu().GetMenuId())
  166.        {
  167.            TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", guid.ToString().c_str());
  168.            return;
  169.        }
  170.    }
  171.    else
  172.    {
  173.        TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - unsupported %s.", guid.ToString().c_str());
  174.        return;
  175.    }
  176.  
  177.    // remove fake death
  178.    if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
  179.        GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
  180.  
  181.    if ((unit && unit->GetCreatureTemplate()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID))
  182.    {
  183.        TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id");
  184.        if (unit)
  185.            unit->LastUsedScriptID = unit->GetCreatureTemplate()->ScriptID;
  186.        if (go)
  187.            go->LastUsedScriptID = go->GetGOInfo()->ScriptId;
  188.        _player->PlayerTalkClass->SendCloseGossip();
  189.        return;
  190.    }
  191.    if (!code.empty())
  192.    {
  193.        if (unit)
  194.        {
  195.            unit->AI()->sGossipSelectCode(_player, menuId, gossipListId, code.c_str());
  196.            if (!sScriptMgr->OnGossipSelectCode(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str()))
  197.                _player->OnGossipSelect(unit, gossipListId, menuId);
  198.        }
  199. #ifdef ELUNA
  200.        else if (item)
  201.        {
  202.            sEluna->HandleGossipSelectOption(GetPlayer(), item, GetPlayer()->PlayerTalkClass->GetGossipOptionSender(gossipListId), GetPlayer()->PlayerTalkClass->GetGossipOptionAction(gossipListId), code);
  203.        }
  204.        else if (_player->GetGUID() == guid && menuId == _player->PlayerTalkClass->GetGossipMenu().GetMenuId())
  205.        {
  206.            sEluna->HandleGossipSelectOption(GetPlayer(), menuId, GetPlayer()->PlayerTalkClass->GetGossipOptionSender(gossipListId), GetPlayer()->PlayerTalkClass->GetGossipOptionAction(gossipListId), code);
  207.        }
  208. #endif
  209.        else if (go)
  210.        {
  211.            go->AI()->GossipSelectCode(_player, menuId, gossipListId, code.c_str());
  212.            if (!sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str()))
  213.                _player->OnGossipSelect(go, gossipListId, menuId);
  214.        }
  215.        else if (item)
  216.        {
  217.            sScriptMgr->OnGossipSelectCode(_player, item, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str());
  218.        }
  219.        else
  220.        {
  221.            sScriptMgr->OnGossipSelectCode(_player, menuId, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str());
  222.        }
  223.    }
  224.    else
  225.    {
  226.        if (unit)
  227.        {
  228.            unit->AI()->sGossipSelect(_player, menuId, gossipListId);
  229.            if (!sScriptMgr->OnGossipSelect(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId)))
  230.                _player->OnGossipSelect(unit, gossipListId, menuId);
  231.        }
  232. #ifdef ELUNA
  233.        else if (_player->GetGUID() == guid && menuId == _player->PlayerTalkClass->GetGossipMenu().GetMenuId())
  234.        {
  235.            sEluna->HandleGossipSelectOption(GetPlayer(), menuId, GetPlayer()->PlayerTalkClass->GetGossipOptionSender(gossipListId), GetPlayer()->PlayerTalkClass->GetGossipOptionAction(gossipListId), code);
  236.        }
  237.        else if (item)
  238.        {
  239.            sEluna->HandleGossipSelectOption(GetPlayer(), item, GetPlayer()->PlayerTalkClass->GetGossipOptionSender(gossipListId), GetPlayer()->PlayerTalkClass->GetGossipOptionAction(gossipListId), code);
  240.        }
  241. #endif
  242.        else if (go)
  243.        {
  244.            go->AI()->GossipSelect(_player, menuId, gossipListId);
  245.            if (!sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId)))
  246.                _player->OnGossipSelect(go, gossipListId, menuId);
  247.        }
  248.        else if (item)
  249.        {
  250.            sScriptMgr->OnGossipSelect(_player, item, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId));
  251.        }
  252.        else
  253.        {
  254.            sScriptMgr->OnGossipSelect(_player, menuId, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId));
  255.        }
  256.    }
  257. }
  258.  
  259. void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
  260. {
  261.    TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_WHO Message");
  262.  
  263.    uint32 matchcount = 0;
  264.  
  265.    uint32 level_min, level_max, racemask, classmask, zones_count, str_count;
  266.    uint32 zoneids[10];                                     // 10 is client limit
  267.    std::string player_name, guild_name;
  268.  
  269.    recvData >> level_min;                                 // maximal player level, default 0
  270.    recvData >> level_max;                                 // minimal player level, default 100 (MAX_LEVEL)
  271.    recvData >> player_name;                               // player name, case sensitive...
  272.  
  273.    recvData >> guild_name;                                // guild name, case sensitive...
  274.  
  275.    recvData >> racemask;                                  // race mask
  276.    recvData >> classmask;                                 // class mask
  277.    recvData >> zones_count;                               // zones count, client limit = 10 (2.0.10)
  278.  
  279.    if (zones_count > 10)
  280.        return;                                             // can't be received from real client or broken packet
  281.  
  282.     for (uint32 i = 0; i < zones_count; ++i)
  283.     {
  284.         uint32 temp;
  285.         recvData >> temp;                                  // zone id, 0 if zone is unknown...
  286.         zoneids[i] = temp;
  287.         TC_LOG_DEBUG("network", "Zone %u: %u", i, zoneids[i]);
  288.     }
  289.  
  290.     recvData >> str_count;                                 // user entered strings count, client limit=4 (checked on 2.0.10)
  291.  
  292.     if (str_count > 4)
  293.         return;                                             // can't be received from real client or broken packet
  294.  
  295.    TC_LOG_DEBUG("network", "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);
  296.  
  297.    std::wstring str[4];                                    // 4 is client limit
  298.    for (uint32 i = 0; i < str_count; ++i)
  299.    {
  300.        std::string temp;
  301.        recvData >> temp;                                  // user entered string, it used as universal search pattern(guild+player name)?
  302.  
  303.        if (!Utf8toWStr(temp, str[i]))
  304.            continue;
  305.  
  306.        wstrToLower(str[i]);
  307.  
  308.        TC_LOG_DEBUG("network", "String %u: %s", i, temp.c_str());
  309.    }
  310.  
  311.    std::wstring wplayer_name;
  312.    std::wstring wguild_name;
  313.    if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name)))
  314.        return;
  315.    wstrToLower(wplayer_name);
  316.    wstrToLower(wguild_name);
  317.  
  318.    // client send in case not set max level value 100 but Trinity supports 255 max level,
  319.    // update it to show GMs with characters after 100 level
  320.    if (level_max >= MAX_LEVEL)
  321.        level_max = STRONG_MAX_LEVEL;
  322.  
  323.    uint32 team = _player->GetTeam();
  324.  
  325.    uint32 gmLevelInWhoList  = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST);
  326.    uint32 displaycount = 0;
  327.  
  328.    WorldPacket data(SMSG_WHO, 50);                       // guess size
  329.    data << uint32(matchcount);                           // placeholder, count of players matching criteria
  330.    data << uint32(displaycount);                         // placeholder, count of players displayed
  331.  
  332.    boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
  333.  
  334.    HashMapHolder<Player>::MapType const& m = ObjectAccessor::GetPlayers();
  335.    for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
  336.    {
  337.        Player* target = itr->second;
  338.        // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
  339.        if (target->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
  340.            continue;
  341.  
  342.        /*// player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST
  343.        if (!HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList))
  344.            continue;*/
  345.  
  346.        // do not process players which are not in world
  347.        if (!target->IsInWorld())
  348.            continue;
  349.  
  350.        // check if target is globally visible for player
  351.        if (!target->IsVisibleGloballyFor(_player))
  352.            continue;
  353.  
  354.        // check if target's level is in level range
  355.         uint8 lvl = target->getLevel();
  356.         if (lvl < level_min || lvl > level_max)
  357.             continue;
  358.  
  359.         // check if class matches classmask
  360.         uint8 class_ = target->getClass();
  361.         if (!(classmask & (1 << class_)))
  362.             continue;
  363.  
  364.         // check if race matches racemask
  365.         uint32 race = target->getRace();
  366.         if (!(racemask & (1 << race)))
  367.             continue;
  368.  
  369.         uint32 pzoneid = target->GetZoneId();
  370.         uint8 gender = target->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER);
  371.  
  372.         bool z_show = true;
  373.         for (uint32 i = 0; i < zones_count; ++i)
  374.         {
  375.             if (zoneids[i] == pzoneid)
  376.             {
  377.                 z_show = true;
  378.                 break;
  379.             }
  380.  
  381.             z_show = false;
  382.         }
  383.         if (!z_show)
  384.             continue;
  385.  
  386.         std::string pname = target->GetName();
  387.         std::wstring wpname;
  388.         if (!Utf8toWStr(pname, wpname))
  389.             continue;
  390.         wstrToLower(wpname);
  391.  
  392.         if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos))
  393.             continue;
  394.  
  395.         std::string gname = sGuildMgr->GetGuildNameById(target->GetGuildId());
  396.         std::wstring wgname;
  397.         if (!Utf8toWStr(gname, wgname))
  398.             continue;
  399.         wstrToLower(wgname);
  400.  
  401.         if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos))
  402.             continue;
  403.  
  404.         std::string aname;
  405.         if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(pzoneid))
  406.             aname = areaEntry->area_name[GetSessionDbcLocale()];
  407.  
  408.         bool s_show = true;
  409.         for (uint32 i = 0; i < str_count; ++i)
  410.         {
  411.             if (!str[i].empty())
  412.             {
  413.                 if (wgname.find(str[i]) != std::wstring::npos ||
  414.                     wpname.find(str[i]) != std::wstring::npos ||
  415.                     Utf8FitTo(aname, str[i]))
  416.                 {
  417.                     s_show = true;
  418.                     break;
  419.                 }
  420.                 s_show = false;
  421.             }
  422.         }
  423.         if (!s_show)
  424.             continue;
  425.  
  426.         // 49 is maximum player count sent to client - can be overridden
  427.         // through config, but is unstable
  428.         if ((matchcount++) >= sWorld->getIntConfig(CONFIG_MAX_WHO))
  429.             continue;
  430.  
  431.         data << pname;                                    // player name
  432.         data << gname;                                    // guild name
  433.         data << uint32(lvl);                              // player level
  434.         data << uint32(class_);                           // player class
  435.         data << uint32(race);                             // player race
  436.         data << uint8(gender);                            // player gender
  437.         data << uint32(pzoneid);                          // player zone id
  438.  
  439.         ++displaycount;
  440.     }
  441.  
  442.     data.put(0, displaycount);                            // insert right count, count displayed
  443.     data.put(4, matchcount);                              // insert right count, count of matches
  444.  
  445.     SendPacket(&data);
  446.     TC_LOG_DEBUG("network", "WORLD: Send SMSG_WHO Message");
  447. }
  448.  
  449. void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/)
  450. {
  451.     TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity());
  452.  
  453.     if (ObjectGuid lguid = GetPlayer()->GetLootGUID())
  454.         DoLootRelease(lguid);
  455.  
  456.     bool instantLogout = (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && !GetPlayer()->IsInCombat()) ||
  457.                          GetPlayer()->IsInFlight() || HasPermission(rbac::RBAC_PERM_INSTANT_LOGOUT);
  458.  
  459.     /// TODO: Possibly add RBAC permission to log out in combat
  460.     bool canLogoutInCombat = GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
  461.  
  462.     uint32 reason = 0;
  463.     if (GetPlayer()->IsInCombat() && !canLogoutInCombat)
  464.         reason = 1;
  465.     else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR))
  466.         reason = 3;                                         // is jumping or falling
  467.     else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command
  468.         reason = 2;                                         // FIXME - Need the correct value
  469.  
  470.     WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4);
  471.     data << uint32(reason);
  472.     data << uint8(instantLogout);
  473.     SendPacket(&data);
  474.  
  475.     if (reason)
  476.     {
  477.         LogoutRequest(0);
  478.         return;
  479.     }
  480.  
  481.     //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in worldserver.conf
  482.     if (instantLogout)
  483.     {
  484.         LogoutPlayer(true);
  485.         return;
  486.     }
  487.  
  488.     // not set flags if player can't free move to prevent lost state at logout cancel
  489.    if (GetPlayer()->CanFreeMove())
  490.    {
  491.        if (GetPlayer()->GetStandState() == UNIT_STAND_STATE_STAND)
  492.            GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT);
  493.  
  494.        WorldPacket data(SMSG_FORCE_MOVE_ROOT, (8+4));    // guess size
  495.        data << GetPlayer()->GetPackGUID();
  496.        data << (uint32)2;
  497.        SendPacket(&data);
  498.        GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
  499.    }
  500.  
  501.    LogoutRequest(time(NULL));
  502. }
  503.  
  504. void WorldSession::HandlePlayerLogoutOpcode(WorldPacket& /*recvData*/)
  505. {
  506.    TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_PLAYER_LOGOUT Message");
  507. }
  508.  
  509. void WorldSession::HandleLogoutCancelOpcode(WorldPacket& /*recvData*/)
  510. {
  511.    TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LOGOUT_CANCEL Message");
  512.  
  513.    // Player have already logged out serverside, too late to cancel
  514.    if (!GetPlayer())
  515.        return;
  516.  
  517.    LogoutRequest(0);
  518.  
  519.    WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0);
  520.    SendPacket(&data);
  521.  
  522.    // not remove flags if can't free move - its not set in Logout request code.
  523.     if (GetPlayer()->CanFreeMove())
  524.     {
  525.         //!we can move again
  526.         data.Initialize(SMSG_FORCE_MOVE_UNROOT, 8);       // guess size
  527.         data << GetPlayer()->GetPackGUID();
  528.         data << uint32(0);
  529.         SendPacket(&data);
  530.  
  531.         //! Stand Up
  532.         GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND);
  533.  
  534.         //! DISABLE_ROTATE
  535.         GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
  536.     }
  537.  
  538.     TC_LOG_DEBUG("network", "WORLD: Sent SMSG_LOGOUT_CANCEL_ACK Message");
  539. }
  540.  
  541. void WorldSession::HandleTogglePvP(WorldPacket& recvData)
  542. {
  543.     // this opcode can be used in two ways: Either set explicit new status or toggle old status
  544.     if (recvData.size() == 1)
  545.     {
  546.         bool newPvPStatus;
  547.         recvData >> newPvPStatus;
  548.         GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus);
  549.         GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus);
  550.     }
  551.     else
  552.     {
  553.         GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP);
  554.         GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER);
  555.     }
  556.  
  557.     if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
  558.     {
  559.         if (!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.EndTimer)
  560.             GetPlayer()->UpdatePvP(true, true);
  561.     }
  562.     else
  563.     {
  564.         if (!GetPlayer()->pvpInfo.IsHostile && GetPlayer()->IsPvP())
  565.             GetPlayer()->pvpInfo.EndTimer = time(NULL);     // start toggle-off
  566.     }
  567.  
  568.     //if (OutdoorPvP* pvp = _player->GetOutdoorPvP())
  569.     //    pvp->HandlePlayerActivityChanged(_player);
  570. }
  571.  
  572. void WorldSession::HandleZoneUpdateOpcode(WorldPacket& recvData)
  573. {
  574.     uint32 newZone;
  575.     recvData >> newZone;
  576.  
  577.     TC_LOG_DEBUG("network", "WORLD: Recvd ZONE_UPDATE: %u", newZone);
  578.  
  579.     // use server side data, but only after update the player position. See Player::UpdatePosition().
  580.     GetPlayer()->SetNeedsZoneUpdate(true);
  581.  
  582.     //GetPlayer()->SendInitWorldStates(true, newZone);
  583. }
  584.  
  585. void WorldSession::HandleSetSelectionOpcode(WorldPacket& recvData)
  586. {
  587.     ObjectGuid guid;
  588.     recvData >> guid;
  589.  
  590.     _player->SetSelection(guid);
  591. }
  592.  
  593. void WorldSession::HandleStandStateChangeOpcode(WorldPacket& recvData)
  594. {
  595.     // TC_LOG_DEBUG("network", "WORLD: Received CMSG_STANDSTATECHANGE"); -- too many spam in log at lags/debug stop
  596.     uint32 animstate;
  597.     recvData >> animstate;
  598.  
  599.     _player->SetStandState(animstate);
  600. }
  601.  
  602. void WorldSession::HandleContactListOpcode(WorldPacket& recvData)
  603. {
  604.     uint32 unk;
  605.     recvData >> unk;
  606.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_CONTACT_LIST - Unk: %d", unk);
  607.     _player->GetSocial()->SendSocialList(_player);
  608. }
  609.  
  610. void WorldSession::HandleAddFriendOpcode(WorldPacket& recvData)
  611. {
  612.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_ADD_FRIEND");
  613.  
  614.     std::string friendName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN);
  615.     std::string friendNote;
  616.  
  617.     recvData >> friendName;
  618.  
  619.     recvData >> friendNote;
  620.  
  621.     if (!normalizePlayerName(friendName))
  622.         return;
  623.  
  624.     TC_LOG_DEBUG("network", "WORLD: %s asked to add friend : '%s'",
  625.         GetPlayer()->GetName().c_str(), friendName.c_str());
  626.  
  627.     PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME);
  628.  
  629.     stmt->setString(0, friendName);
  630.  
  631.     _addFriendCallback.SetParam(friendNote);
  632.     _addFriendCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
  633. }
  634.  
  635. void WorldSession::HandleAddFriendOpcodeCallBack(PreparedQueryResult result, std::string const& friendNote)
  636. {
  637.     if (!GetPlayer())
  638.         return;
  639.  
  640.     ObjectGuid friendGuid;
  641.     uint32 friendAccountId;
  642.     uint32 team;
  643.     FriendsResult friendResult;
  644.  
  645.     friendResult = FRIEND_NOT_FOUND;
  646.  
  647.     if (result)
  648.     {
  649.         Field* fields = result->Fetch();
  650.  
  651.         friendGuid = ObjectGuid(HighGuid::Player, 0, fields[0].GetUInt32());
  652.         team = Player::TeamForRace(fields[1].GetUInt8());
  653.         friendAccountId = fields[2].GetUInt32();
  654.  
  655.         if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
  656.         {
  657.             if (friendGuid)
  658.             {
  659.                 if (friendGuid == GetPlayer()->GetGUID())
  660.                     friendResult = FRIEND_SELF;
  661.                 else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
  662.                     friendResult = FRIEND_ENEMY;
  663.                 else if (GetPlayer()->GetSocial()->HasFriend(friendGuid.GetCounter()))
  664.                     friendResult = FRIEND_ALREADY;
  665.                 else
  666.                 {
  667.                     Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
  668.                     if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer()))
  669.                         friendResult = FRIEND_ADDED_ONLINE;
  670.                     else
  671.                         friendResult = FRIEND_ADDED_OFFLINE;
  672.                     if (!GetPlayer()->GetSocial()->AddToSocialList(friendGuid.GetCounter(), false))
  673.                     {
  674.                         friendResult = FRIEND_LIST_FULL;
  675.                         TC_LOG_DEBUG("network", "WORLD: %s's friend list is full.", GetPlayer()->GetName().c_str());
  676.                     }
  677.                 }
  678.                 GetPlayer()->GetSocial()->SetFriendNote(friendGuid.GetCounter(), friendNote);
  679.             }
  680.         }
  681.     }
  682.  
  683.     sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, friendGuid.GetCounter(), false);
  684.  
  685.     TC_LOG_DEBUG("network", "WORLD: Sent (SMSG_FRIEND_STATUS)");
  686. }
  687.  
  688. void WorldSession::HandleDelFriendOpcode(WorldPacket& recvData)
  689. {
  690.     ObjectGuid FriendGUID;
  691.  
  692.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_DEL_FRIEND");
  693.  
  694.     recvData >> FriendGUID;
  695.  
  696.     _player->GetSocial()->RemoveFromSocialList(FriendGUID.GetCounter(), false);
  697.  
  698.     sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_REMOVED, FriendGUID.GetCounter(), false);
  699.  
  700.     TC_LOG_DEBUG("network", "WORLD: Sent motd (SMSG_FRIEND_STATUS)");
  701. }
  702.  
  703. void WorldSession::HandleAddIgnoreOpcode(WorldPacket& recvData)
  704. {
  705.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_ADD_IGNORE");
  706.  
  707.     std::string ignoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN);
  708.  
  709.     recvData >> ignoreName;
  710.  
  711.     if (!normalizePlayerName(ignoreName))
  712.         return;
  713.  
  714.     TC_LOG_DEBUG("network", "WORLD: %s asked to Ignore: '%s'",
  715.         GetPlayer()->GetName().c_str(), ignoreName.c_str());
  716.  
  717.     PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME);
  718.  
  719.     stmt->setString(0, ignoreName);
  720.  
  721.     _addIgnoreCallback = CharacterDatabase.AsyncQuery(stmt);
  722. }
  723.  
  724. void WorldSession::HandleAddIgnoreOpcodeCallBack(PreparedQueryResult result)
  725. {
  726.     if (!GetPlayer())
  727.         return;
  728.  
  729.     ObjectGuid IgnoreGuid;
  730.     FriendsResult ignoreResult;
  731.  
  732.     ignoreResult = FRIEND_IGNORE_NOT_FOUND;
  733.  
  734.     if (result)
  735.     {
  736.         IgnoreGuid = ObjectGuid(HighGuid::Player, (*result)[0].GetUInt32());
  737.  
  738.         if (IgnoreGuid)
  739.         {
  740.             if (IgnoreGuid == GetPlayer()->GetGUID())              //not add yourself
  741.                 ignoreResult = FRIEND_IGNORE_SELF;
  742.             else if (GetPlayer()->GetSocial()->HasIgnore(IgnoreGuid.GetCounter()))
  743.                 ignoreResult = FRIEND_IGNORE_ALREADY;
  744.             else
  745.             {
  746.                 ignoreResult = FRIEND_IGNORE_ADDED;
  747.  
  748.                 // ignore list full
  749.                 if (!GetPlayer()->GetSocial()->AddToSocialList(IgnoreGuid.GetCounter(), true))
  750.                     ignoreResult = FRIEND_IGNORE_FULL;
  751.             }
  752.         }
  753.     }
  754.  
  755.     sSocialMgr->SendFriendStatus(GetPlayer(), ignoreResult, IgnoreGuid.GetCounter(), false);
  756.  
  757.     TC_LOG_DEBUG("network", "WORLD: Sent (SMSG_FRIEND_STATUS)");
  758. }
  759.  
  760. void WorldSession::HandleDelIgnoreOpcode(WorldPacket& recvData)
  761. {
  762.     ObjectGuid IgnoreGUID;
  763.  
  764.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_DEL_IGNORE");
  765.  
  766.     recvData >> IgnoreGUID;
  767.  
  768.     _player->GetSocial()->RemoveFromSocialList(IgnoreGUID.GetCounter(), true);
  769.  
  770.     sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, IgnoreGUID.GetCounter(), false);
  771.  
  772.     TC_LOG_DEBUG("network", "WORLD: Sent motd (SMSG_FRIEND_STATUS)");
  773. }
  774.  
  775. void WorldSession::HandleSetContactNotesOpcode(WorldPacket& recvData)
  776. {
  777.     TC_LOG_DEBUG("network", "CMSG_SET_CONTACT_NOTES");
  778.     ObjectGuid guid;
  779.     std::string note;
  780.     recvData >> guid >> note;
  781.     _player->GetSocial()->SetFriendNote(guid.GetCounter(), note);
  782. }
  783.  
  784. void WorldSession::HandleBugOpcode(WorldPacket& recvData)
  785. {
  786.     uint32 suggestion, contentlen, typelen;
  787.     std::string content, type;
  788.  
  789.     recvData >> suggestion >> contentlen >> content;
  790.  
  791.     recvData >> typelen >> type;
  792.  
  793.     if (suggestion == 0)
  794.         TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUG [Bug Report]");
  795.     else
  796.         TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUG [Suggestion]");
  797.  
  798.     TC_LOG_DEBUG("network", "%s", type.c_str());
  799.     TC_LOG_DEBUG("network", "%s", content.c_str());
  800.  
  801.     PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_BUG_REPORT);
  802.  
  803.     stmt->setString(0, type);
  804.     stmt->setString(1, content);
  805.  
  806.     CharacterDatabase.Execute(stmt);
  807. }
  808.  
  809. void WorldSession::HandleReclaimCorpseOpcode(WorldPacket& recvData)
  810. {
  811.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_RECLAIM_CORPSE");
  812.  
  813.     ObjectGuid guid;
  814.     recvData >> guid;
  815.  
  816.     if (_player->IsAlive())
  817.         return;
  818.  
  819.     // do not allow corpse reclaim in arena
  820.     if (_player->InArena())
  821.         return;
  822.  
  823.     // body not released yet
  824.     if (!_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
  825.         return;
  826.  
  827.     Corpse* corpse = _player->GetCorpse();
  828.     if (!corpse)
  829.         return;
  830.  
  831.     // prevent resurrect before 30-sec delay after body release not finished
  832.     if (time_t(corpse->GetGhostTime() + _player->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP)) > time_t(time(NULL)))
  833.         return;
  834.  
  835.     if (!corpse->IsWithinDistInMap(_player, CORPSE_RECLAIM_RADIUS, true))
  836.         return;
  837.  
  838.     // resurrect
  839.     _player->ResurrectPlayer(_player->InBattleground() ? 1.0f : 0.5f);
  840.  
  841.     // spawn bones
  842.     _player->SpawnCorpseBones();
  843. }
  844.  
  845. void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData)
  846. {
  847.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_RESURRECT_RESPONSE");
  848.  
  849.     ObjectGuid guid;
  850.     uint8 status;
  851.     recvData >> guid;
  852.     recvData >> status;
  853.  
  854.     if (GetPlayer()->IsAlive())
  855.         return;
  856.  
  857.     if (status == 0)
  858.     {
  859.         GetPlayer()->ClearResurrectRequestData();           // reject
  860.         return;
  861.     }
  862.  
  863.     if (!GetPlayer()->IsResurrectRequestedBy(guid))
  864.         return;
  865.  
  866.     GetPlayer()->ResurrectUsingRequestData();
  867. }
  868.  
  869. void WorldSession::SendAreaTriggerMessage(const char* Text, ...)
  870. {
  871.     va_list ap;
  872.     char szStr [1024];
  873.     szStr[0] = '\0';
  874.  
  875.     va_start(ap, Text);
  876.     vsnprintf(szStr, 1024, Text, ap);
  877.     va_end(ap);
  878.  
  879.     uint32 length = strlen(szStr)+1;
  880.     WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 4+length);
  881.     data << length;
  882.     data << szStr;
  883.     SendPacket(&data);
  884. }
  885.  
  886. void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
  887. {
  888.     uint32 triggerId;
  889.     recvData >> triggerId;
  890.  
  891.     TC_LOG_DEBUG("network", "CMSG_AREATRIGGER. Trigger ID: %u", triggerId);
  892.  
  893.     Player* player = GetPlayer();
  894.     if (player->IsInFlight())
  895.     {
  896.         TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u",
  897.             player->GetName().c_str(), player->GetGUID().GetCounter(), triggerId);
  898.         return;
  899.     }
  900.  
  901.     AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(triggerId);
  902.     if (!atEntry)
  903.     {
  904.         TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) send unknown (by DBC) Area Trigger ID:%u",
  905.             player->GetName().c_str(), player->GetGUID().GetCounter(), triggerId);
  906.         return;
  907.     }
  908.  
  909.     if (!player->IsInAreaTriggerRadius(atEntry))
  910.     {
  911.         TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (GUID: %u) too far, ignore Area Trigger ID: %u",
  912.             player->GetName().c_str(), player->GetGUID().GetCounter(), triggerId);
  913.         return;
  914.     }
  915.  
  916.     if (player->isDebugAreaTriggers)
  917.         ChatHandler(player->GetSession()).PSendSysMessage(LANG_DEBUG_AREATRIGGER_REACHED, triggerId);
  918.  
  919.     if (sScriptMgr->OnAreaTrigger(player, atEntry))
  920.         return;
  921.  
  922.     if (player->IsAlive())
  923.         if (uint32 questId = sObjectMgr->GetQuestForAreaTrigger(triggerId))
  924.             if (player->GetQuestStatus(questId) == QUEST_STATUS_INCOMPLETE)
  925.                 player->AreaExploredOrEventHappens(questId);
  926.  
  927.     if (sObjectMgr->IsTavernAreaTrigger(triggerId))
  928.     {
  929.         // set resting flag we are in the inn
  930.         player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->id);
  931.  
  932.         if (sWorld->IsFFAPvPRealm())
  933.             player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
  934.  
  935.         return;
  936.     }
  937.  
  938.     if (Battleground* bg = player->GetBattleground())
  939.         if (bg->GetStatus() == STATUS_IN_PROGRESS)
  940.             bg->HandleAreaTrigger(player, triggerId);
  941.  
  942.     if (OutdoorPvP* pvp = player->GetOutdoorPvP())
  943.         if (pvp->HandleAreaTrigger(_player, triggerId))
  944.             return;
  945.  
  946.     AreaTrigger const* at = sObjectMgr->GetAreaTrigger(triggerId);
  947.     if (!at)
  948.         return;
  949.  
  950.     bool teleported = false;
  951.     if (player->GetMapId() != at->target_mapId)
  952.     {
  953.         if (Map::EnterState denyReason = sMapMgr->PlayerCannotEnter(at->target_mapId, player, false))
  954.         {
  955.             bool reviveAtTrigger = false; // should we revive the player if he is trying to enter the correct instance?
  956.             switch (denyReason)
  957.             {
  958.                 case Map::CANNOT_ENTER_NO_ENTRY:
  959.                     TC_LOG_DEBUG("maps", "MAP: Player '%s' attempted to enter map with id %d which has no entry", player->GetName().c_str(), at->target_mapId);
  960.                     break;
  961.                 case Map::CANNOT_ENTER_UNINSTANCED_DUNGEON:
  962.                     TC_LOG_DEBUG("maps", "MAP: Player '%s' attempted to enter dungeon map %d but no instance template was found", player->GetName().c_str(), at->target_mapId);
  963.                     break;
  964.                 case Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE:
  965.                     TC_LOG_DEBUG("maps", "MAP: Player '%s' attempted to enter instance map %d but the requested difficulty was not found", player->GetName().c_str(), at->target_mapId);
  966.                     if (MapEntry const* entry = sMapStore.LookupEntry(at->target_mapId))
  967.                         player->SendTransferAborted(entry->MapID, TRANSFER_ABORT_DIFFICULTY, player->GetDifficulty(entry->IsRaid()));
  968.                     break;
  969.                 case Map::CANNOT_ENTER_NOT_IN_RAID:
  970.                 {
  971.                     WorldPacket data(SMSG_RAID_GROUP_ONLY, 4 + 4);
  972.                     data << uint32(0);
  973.                     data << uint32(2); // You must be in a raid group to enter this instance.
  974.                     player->GetSession()->SendPacket(&data);
  975.                     TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance map %d", player->GetName().c_str(), at->target_mapId);
  976.                     reviveAtTrigger = true;
  977.                     break;
  978.                 }
  979.                 case Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE:
  980.                 {
  981.                     WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE);
  982.                     player->GetSession()->SendPacket(&data);
  983.                     TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance map %d and cannot enter", player->GetName().c_str(), at->target_mapId);
  984.                     break;
  985.                 }
  986.                 case Map::CANNOT_ENTER_INSTANCE_BIND_MISMATCH:
  987.                     if (MapEntry const* entry = sMapStore.LookupEntry(at->target_mapId))
  988.                     {
  989.                         char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
  990.                         TC_LOG_DEBUG("maps", "MAP: Player '%s' cannot enter instance map '%s' because their permanent bind is incompatible with their group's", player->GetName().c_str(), mapName);
  991.                         // is there a special opcode for this?
  992.                         // @todo figure out how to get player localized difficulty string (e.g. "10 player", "Heroic" etc)
  993.                         ChatHandler(player->GetSession()).PSendSysMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_BIND_MISMATCH), mapName);
  994.                     }
  995.                     reviveAtTrigger = true;
  996.                     break;
  997.                 case Map::CANNOT_ENTER_TOO_MANY_INSTANCES:
  998.                     player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_TOO_MANY_INSTANCES);
  999.                     TC_LOG_DEBUG("maps", "MAP: Player '%s' cannot enter instance map %d because he has exceeded the maximum number of instances per hour.", player->GetName().c_str(), at->target_mapId);
  1000.                     reviveAtTrigger = true;
  1001.                     break;
  1002.                 case Map::CANNOT_ENTER_MAX_PLAYERS:
  1003.                     player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_MAX_PLAYERS);
  1004.                     reviveAtTrigger = true;
  1005.                     break;
  1006.                 case Map::CANNOT_ENTER_ZONE_IN_COMBAT:
  1007.                     player->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_ZONE_IN_COMBAT);
  1008.                     reviveAtTrigger = true;
  1009.                     break;
  1010.                 default:
  1011.                     break;
  1012.             }
  1013.  
  1014.             if (reviveAtTrigger) // check if the player is touching the areatrigger leading to the map his corpse is on
  1015.                 if (!player->IsAlive() && player->HasCorpse())
  1016.                     if (player->GetCorpseLocation().GetMapId() == at->target_mapId)
  1017.                     {
  1018.                         player->ResurrectPlayer(0.5f);
  1019.                         player->SpawnCorpseBones();
  1020.                     }
  1021.  
  1022.             return;
  1023.         }
  1024.  
  1025.         if (Group* group = player->GetGroup())
  1026.             if (group->isLFGGroup() && player->GetMap()->IsDungeon())
  1027.                 teleported = player->TeleportToBGEntryPoint();
  1028.     }
  1029.  
  1030.     if (!teleported)
  1031.         player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT);
  1032. }
  1033.  
  1034. void WorldSession::HandleUpdateAccountData(WorldPacket& recvData)
  1035. {
  1036.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_UPDATE_ACCOUNT_DATA");
  1037.  
  1038.     uint32 type, timestamp, decompressedSize;
  1039.     recvData >> type >> timestamp >> decompressedSize;
  1040.  
  1041.     TC_LOG_DEBUG("network", "UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize);
  1042.  
  1043.     if (type > NUM_ACCOUNT_DATA_TYPES)
  1044.         return;
  1045.  
  1046.     if (decompressedSize == 0)                               // erase
  1047.     {
  1048.         SetAccountData(AccountDataType(type), 0, "");
  1049.  
  1050.         WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4);
  1051.         data << uint32(type);
  1052.         data << uint32(0);
  1053.         SendPacket(&data);
  1054.  
  1055.         return;
  1056.     }
  1057.  
  1058.     if (decompressedSize > 0xFFFF)
  1059.     {
  1060.         recvData.rfinish();                   // unnneded warning spam in this case
  1061.         TC_LOG_ERROR("network", "UAD: Account data packet too big, size %u", decompressedSize);
  1062.         return;
  1063.     }
  1064.  
  1065.     ByteBuffer dest;
  1066.     dest.resize(decompressedSize);
  1067.  
  1068.     uLongf realSize = decompressedSize;
  1069.     if (uncompress(dest.contents(), &realSize, recvData.contents() + recvData.rpos(), recvData.size() - recvData.rpos()) != Z_OK)
  1070.     {
  1071.         recvData.rfinish();                   // unnneded warning spam in this case
  1072.         TC_LOG_ERROR("network", "UAD: Failed to decompress account data");
  1073.         return;
  1074.     }
  1075.  
  1076.     recvData.rfinish();                       // uncompress read (recvData.size() - recvData.rpos())
  1077.  
  1078.     std::string adata;
  1079.     dest >> adata;
  1080.  
  1081.     SetAccountData(AccountDataType(type), timestamp, adata);
  1082.  
  1083.     WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4);
  1084.     data << uint32(type);
  1085.     data << uint32(0);
  1086.     SendPacket(&data);
  1087. }
  1088.  
  1089. void WorldSession::HandleRequestAccountData(WorldPacket& recvData)
  1090. {
  1091.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_REQUEST_ACCOUNT_DATA");
  1092.  
  1093.     uint32 type;
  1094.     recvData >> type;
  1095.  
  1096.     TC_LOG_DEBUG("network", "RAD: type %u", type);
  1097.  
  1098.     if (type >= NUM_ACCOUNT_DATA_TYPES)
  1099.         return;
  1100.  
  1101.     AccountData* adata = GetAccountData(AccountDataType(type));
  1102.  
  1103.     uint32 size = adata->Data.size();
  1104.  
  1105.     uLongf destSize = compressBound(size);
  1106.  
  1107.     ByteBuffer dest;
  1108.     dest.resize(destSize);
  1109.  
  1110.     if (size && compress(dest.contents(), &destSize, (uint8 const*)adata->Data.c_str(), size) != Z_OK)
  1111.     {
  1112.         TC_LOG_DEBUG("network", "RAD: Failed to compress account data");
  1113.         return;
  1114.     }
  1115.  
  1116.     dest.resize(destSize);
  1117.  
  1118.     WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize);
  1119.     data << uint64(_player ? _player->GetGUID() : ObjectGuid::Empty);
  1120.     data << uint32(type);                                   // type (0-7)
  1121.     data << uint32(adata->Time);                            // unix time
  1122.     data << uint32(size);                                   // decompressed length
  1123.     data.append(dest);                                      // compressed data
  1124.     SendPacket(&data);
  1125. }
  1126.  
  1127. void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData)
  1128. {
  1129.     uint8 button;
  1130.     uint32 packetData;
  1131.     recvData >> button >> packetData;
  1132.     TC_LOG_DEBUG("network", "CMSG_SET_ACTION_BUTTON Button: %u Data: %u", button, packetData);
  1133.  
  1134.     if (!packetData)
  1135.         GetPlayer()->removeActionButton(button);
  1136.     else
  1137.         GetPlayer()->addActionButton(button, ACTION_BUTTON_ACTION(packetData), ACTION_BUTTON_TYPE(packetData));
  1138. }
  1139.  
  1140. void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/)
  1141. {
  1142.     // If player has sight bound to visual waypoint NPC we should remove it
  1143.     GetPlayer()->EndCinematic();
  1144. }
  1145.  
  1146. void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/)
  1147. {
  1148.     // Sent by client when cinematic actually begun. So we begin the server side process
  1149.     GetPlayer()->BeginCinematic();
  1150. }
  1151.  
  1152. void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
  1153. {
  1154.     /*  WorldSession::Update(getMSTime());*/
  1155.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_MOVE_TIME_SKIPPED");
  1156.  
  1157.     ObjectGuid guid;
  1158.     recvData >> guid.ReadAsPacked();
  1159.     recvData.read_skip<uint32>();
  1160.     /*
  1161.         uint64 guid;
  1162.         uint32 time_skipped;
  1163.         recvData >> guid;
  1164.         recvData >> time_skipped;
  1165.         TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_TIME_SKIPPED");
  1166.  
  1167.         //// @todo
  1168.         must be need use in Trinity
  1169.         We substract server Lags to move time (AntiLags)
  1170.         for exmaple
  1171.         GetPlayer()->ModifyLastMoveTime(-int32(time_skipped));
  1172.     */
  1173. }
  1174.  
  1175. void WorldSession::HandleFeatherFallAck(WorldPacket& recvData)
  1176. {
  1177.     TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_FEATHER_FALL_ACK");
  1178.  
  1179.     // no used
  1180.     recvData.rfinish();                       // prevent warnings spam
  1181. }
  1182.  
  1183. void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData)
  1184. {
  1185.     // no used
  1186.     recvData.rfinish();                       // prevent warnings spam
  1187. /*
  1188.     uint64 guid;
  1189.     recvData >> guid;
  1190.  
  1191.     // now can skip not our packet
  1192.     if (_player->GetGUID() != guid)
  1193.     {
  1194.         recvData.rfinish();                   // prevent warnings spam
  1195.         return;
  1196.     }
  1197.  
  1198.     TC_LOG_DEBUG("network", "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK");
  1199.  
  1200.     recvData.read_skip<uint32>();                          // unk
  1201.  
  1202.     MovementInfo movementInfo;
  1203.     movementInfo.guid = guid;
  1204.     ReadMovementInfo(recvData, &movementInfo);
  1205.     recvData.read_skip<float>();                           // unk2
  1206. */
  1207. }
  1208.  
  1209. void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
  1210. {
  1211.     // no used
  1212.     recvData.rfinish();                       // prevent warnings spam
  1213. /*
  1214.     uint64 guid;
  1215.     recvData >> guid;
  1216.  
  1217.     // now can skip not our packet
  1218.     if (_player->GetGUID() != guid)
  1219.     {
  1220.         recvData.rfinish();                   // prevent warnings spam
  1221.         return;
  1222.     }
  1223.  
  1224.     TC_LOG_DEBUG("network", "WORLD: CMSG_FORCE_MOVE_ROOT_ACK");
  1225.  
  1226.     recvData.read_skip<uint32>();                          // unk
  1227.  
  1228.     MovementInfo movementInfo;
  1229.     ReadMovementInfo(recvData, &movementInfo);
  1230. */
  1231. }
  1232.  
  1233. void WorldSession::HandleSetActionBarToggles(WorldPacket& recvData)
  1234. {
  1235.     uint8 actionBar;
  1236.     recvData >> actionBar;
  1237.  
  1238.     if (!GetPlayer())                                        // ignore until not logged (check needed because STATUS_AUTHED)
  1239.     {
  1240.         if (actionBar != 0)
  1241.             TC_LOG_ERROR("network", "WorldSession::HandleSetActionBarToggles in not logged state with value: %u, ignored", uint32(actionBar));
  1242.         return;
  1243.     }
  1244.  
  1245.     GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, actionBar);
  1246. }
  1247.  
  1248. void WorldSession::HandlePlayedTime(WorldPacket& recvData)
  1249. {
  1250.     uint8 unk1;
  1251.     recvData >> unk1;                                      // 0 or 1 expected
  1252.  
  1253.     WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1);
  1254.     data << uint32(_player->GetTotalPlayedTime());
  1255.     data << uint32(_player->GetLevelPlayedTime());
  1256.     data << uint8(unk1);                                    // 0 - will not show in chat frame
  1257.     SendPacket(&data);
  1258. }
  1259.  
  1260. void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
  1261. {
  1262.     ObjectGuid guid;
  1263.     recvData >> guid;
  1264.  
  1265.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_INSPECT");
  1266.  
  1267.     Player* player = ObjectAccessor::FindPlayer(guid);
  1268.     if (!player)
  1269.     {
  1270.         TC_LOG_DEBUG("network", "CMSG_INSPECT: No player found from %s", guid.ToString().c_str());
  1271.         return;
  1272.     }
  1273.  
  1274.     if (!GetPlayer()->IsWithinDistInMap(player, INSPECT_DISTANCE, false))
  1275.         return;
  1276.  
  1277.     if (GetPlayer()->IsValidAttackTarget(player))
  1278.         return;
  1279.  
  1280.     uint32 talent_points = 0x47;
  1281.     uint32 guid_size = player->GetPackGUID().size();
  1282.     WorldPacket data(SMSG_INSPECT_TALENT, guid_size+4+talent_points);
  1283.     data << player->GetPackGUID();
  1284.  
  1285.     if (GetPlayer()->CanBeGameMaster() || sWorld->getIntConfig(CONFIG_TALENTS_INSPECTING) + (GetPlayer()->GetTeamId() == player->GetTeamId()) > 1)
  1286.         player->BuildPlayerTalentsInfoData(&data);
  1287.     else
  1288.     {
  1289.         data << uint32(0);                                  // unspentTalentPoints
  1290.         data << uint8(0);                                   // talentGroupCount
  1291.         data << uint8(0);                                   // talentGroupIndex
  1292.     }
  1293.  
  1294.     player->BuildEnchantmentsInfoData(&data);
  1295.     SendPacket(&data);
  1296. }
  1297.  
  1298. void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recvData)
  1299. {
  1300.     ObjectGuid guid;
  1301.     recvData >> guid;
  1302.  
  1303.     Player* player = ObjectAccessor::FindPlayer(guid);
  1304.  
  1305.     if (!player)
  1306.     {
  1307.         TC_LOG_DEBUG("network", "MSG_INSPECT_HONOR_STATS: No player found from %s", guid.ToString().c_str());
  1308.         return;
  1309.     }
  1310.  
  1311.     if (!GetPlayer()->IsWithinDistInMap(player, INSPECT_DISTANCE, false))
  1312.         return;
  1313.  
  1314.     if (GetPlayer()->IsValidAttackTarget(player))
  1315.         return;
  1316.  
  1317.     WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4);
  1318.     data << uint64(player->GetGUID());
  1319.     data << uint8(player->GetHonorPoints());
  1320.     data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS));
  1321.     data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION));
  1322.     data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION));
  1323.     data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
  1324.     SendPacket(&data);
  1325. }
  1326.  
  1327. void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recvData)
  1328. {
  1329.     uint32 time;
  1330.     uint32 mapid;
  1331.     float PositionX;
  1332.     float PositionY;
  1333.     float PositionZ;
  1334.     float Orientation;
  1335.  
  1336.     recvData >> time;                                      // time in m.sec.
  1337.     recvData >> mapid;
  1338.     recvData >> PositionX;
  1339.     recvData >> PositionY;
  1340.     recvData >> PositionZ;
  1341.     recvData >> Orientation;                               // o (3.141593 = 180 degrees)
  1342.  
  1343.     TC_LOG_DEBUG("network", "WORLD: Received CMSG_WORLD_TELEPORT");
  1344.  
  1345.     if (GetPlayer()->IsInFlight())
  1346.     {
  1347.         TC_LOG_DEBUG("network", "Player '%s' (GUID: %u) in flight, ignore worldport command.",
  1348.             GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().GetCounter());
  1349.         return;
  1350.     }
  1351.  
  1352.     TC_LOG_DEBUG("network", "CMSG_WORLD_TELEPORT: Player = %s, Time = %u, map = %u, x = %f, y = %f, z = %f, o = %f",
  1353.         GetPlayer()->GetName().c_str(), time, mapid, PositionX, PositionY, PositionZ, Orientation);
  1354.  
  1355.     if (HasPermission(rbac::RBAC_PERM_OPCODE_WORLD_TELEPORT))
  1356.         GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation);
  1357.     else
  1358.         SendNotification(LANG_YOU_NOT_HAVE_PERMISSION);
  1359. }
  1360.  
  1361. void WorldSession::HandleWhoisOpcode(WorldPacket& recvData)
  1362. {
  1363.     TC_LOG_DEBUG("network", "Received opcode CMSG_WHOIS");
  1364.     std::string charname;
  1365.     recvData >> charname;
  1366.  
  1367.     if (!HasPermission(rbac::RBAC_PERM_OPCODE_WHOIS))
  1368.     {
  1369.         SendNotification(LANG_YOU_NOT_HAVE_PERMISSION);
  1370.         return;
  1371.     }
  1372.  
  1373.     if (charname.empty() || !normalizePlayerName (charname))
  1374.     {
  1375.         SendNotification(LANG_NEED_CHARACTER_NAME);
  1376.         return;
  1377.     }
  1378.  
  1379.     Player* player = ObjectAccessor::FindConnectedPlayerByName(charname);
  1380.  
  1381.     if (!player)
  1382.     {
  1383.         SendNotification(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, charname.c_str());
  1384.         return;
  1385.     }
  1386.  
  1387.     uint32 accid = player->GetSession()->GetAccountId();
  1388.  
  1389.     PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_WHOIS);
  1390.  
  1391.     stmt->setUInt32(0, accid);
  1392.  
  1393.     PreparedQueryResult result = LoginDatabase.Query(stmt);
  1394.  
  1395.     if (!result)
  1396.     {
  1397.         SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str());
  1398.         return;
  1399.     }
  1400.  
  1401.     Field* fields = result->Fetch();
  1402.     std::string acc = fields[0].GetString();
  1403.     if (acc.empty())
  1404.         acc = "Unknown";
  1405.     std::string email = fields[1].GetString();
  1406.     if (email.empty())
  1407.         email = "Unknown";
  1408.     std::string lastip = fields[2].GetString();
  1409.     if (lastip.empty())
  1410.         lastip = "Unknown";
  1411.  
  1412.     std::string msg = charname + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip;
  1413.  
  1414.     WorldPacket data(SMSG_WHOIS, msg.size()+1);
  1415.     data << msg;
  1416.     SendPacket(&data);
  1417.  
  1418.     TC_LOG_DEBUG("network", "Received whois command from player %s for character %s",
  1419.         GetPlayer()->GetName().c_str(), charname.c_str());
  1420. }
  1421.  
  1422. void WorldSession::HandleComplainOpcode(WorldPacket& recvData)
  1423. {
  1424.     TC_LOG_DEBUG("network", "WORLD: CMSG_COMPLAIN");
  1425.  
  1426.     uint8 spam_type;                                        // 0 - mail, 1 - chat
  1427.     ObjectGuid spammer_guid;
  1428.     uint32 unk1 = 0;
  1429.     uint32 unk2 = 0;
  1430.     uint32 unk3 = 0;
  1431.     uint32 unk4 = 0;
  1432.     std::string description = "";
  1433.     recvData >> spam_type;                                 // unk 0x01 const, may be spam type (mail/chat)
  1434.     recvData >> spammer_guid;                              // player guid
  1435.     switch (spam_type)
  1436.     {
  1437.         case 0:
  1438.             recvData >> unk1;                              // const 0
  1439.             recvData >> unk2;                              // probably mail id
  1440.             recvData >> unk3;                              // const 0
  1441.             break;
  1442.         case 1:
  1443.             recvData >> unk1;                              // probably language
  1444.             recvData >> unk2;                              // message type?
  1445.             recvData >> unk3;                              // probably channel id
  1446.             recvData >> unk4;                              // time
  1447.             recvData >> description;                       // spam description string (messagetype, channel name, player name, message)
  1448.             break;
  1449.     }
  1450.  
  1451.     // NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam.
  1452.     // if it's mail spam - ALL mails from this spammer automatically removed by client
  1453.  
  1454.    // Complaint Received message
  1455.    WorldPacket data(SMSG_COMPLAIN_RESULT, 1);
  1456.    data << uint8(0);
  1457.    SendPacket(&data);
  1458.  
  1459.    TC_LOG_DEBUG("network", "REPORT SPAM: type %u, %s, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s",
  1460.        spam_type, spammer_guid.ToString().c_str(), unk1, unk2, unk3, unk4, description.c_str());
  1461. }
  1462.  
  1463. void WorldSession::HandleRealmSplitOpcode(WorldPacket& recvData)
  1464. {
  1465.    TC_LOG_DEBUG("network", "CMSG_REALM_SPLIT");
  1466.  
  1467.    uint32 unk;
  1468.    std::string split_date = "01/01/01";
  1469.    recvData >> unk;
  1470.  
  1471.    WorldPacket data(SMSG_REALM_SPLIT, 4+4+split_date.size()+1);
  1472.    data << unk;
  1473.    data << uint32(0x00000000);                             // realm split state
  1474.    // split states:
  1475.    // 0x0 realm normal
  1476.    // 0x1 realm split
  1477.    // 0x2 realm split pending
  1478.    data << split_date;
  1479.    SendPacket(&data);
  1480.    //TC_LOG_DEBUG("response sent %u", unk);
  1481. }
  1482.  
  1483. void WorldSession::HandleFarSightOpcode(WorldPacket& recvData)
  1484. {
  1485.    TC_LOG_DEBUG("network", "WORLD: CMSG_FAR_SIGHT");
  1486.  
  1487.    bool apply;
  1488.    recvData >> apply;
  1489.  
  1490.    if (apply)
  1491.    {
  1492.        TC_LOG_DEBUG("network", "Added FarSight %s to player %u", _player->GetGuidValue(PLAYER_FARSIGHT).ToString().c_str(), _player->GetGUID().GetCounter());
  1493.        if (WorldObject* target = _player->GetViewpoint())
  1494.            _player->SetSeer(target);
  1495.        else
  1496.            TC_LOG_ERROR("network", "Player %s (%s) requests non-existing seer %s", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), _player->GetGuidValue(PLAYER_FARSIGHT).ToString().c_str());
  1497.    }
  1498.    else
  1499.    {
  1500.        TC_LOG_DEBUG("network", "Player %u set vision to self", _player->GetGUID().GetCounter());
  1501.        _player->SetSeer(_player);
  1502.    }
  1503.  
  1504.    GetPlayer()->UpdateVisibilityForPlayer();
  1505. }
  1506.  
  1507. void WorldSession::HandleSetTitleOpcode(WorldPacket& recvData)
  1508. {
  1509.    TC_LOG_DEBUG("network", "CMSG_SET_TITLE");
  1510.  
  1511.    int32 title;
  1512.    recvData >> title;
  1513.  
  1514.    // -1 at none
  1515.    if (title > 0 && title < MAX_TITLE_INDEX)
  1516.    {
  1517.       if (!GetPlayer()->HasTitle(title))
  1518.            return;
  1519.    }
  1520.    else
  1521.        title = 0;
  1522.  
  1523.    GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title);
  1524. }
  1525.  
  1526. void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
  1527. {
  1528.    TC_LOG_DEBUG("network", "CMSG_TIME_SYNC_RESP");
  1529.  
  1530.    uint32 counter, clientTicks;
  1531.    recvData >> counter >> clientTicks;
  1532.  
  1533.    if (counter != _player->m_timeSyncCounter - 1)
  1534.        TC_LOG_DEBUG("network", "Wrong time sync counter from player %s (cheater?)", _player->GetName().c_str());
  1535.  
  1536.    TC_LOG_DEBUG("network", "Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient);
  1537.  
  1538.    uint32 ourTicks = clientTicks + (getMSTime() - _player->m_timeSyncServer);
  1539.  
  1540.    // diff should be small
  1541.    TC_LOG_DEBUG("network", "Our ticks: %u, diff %u, latency %u", ourTicks, ourTicks - clientTicks, GetLatency());
  1542.  
  1543.    _player->m_timeSyncClient = clientTicks;
  1544. }
  1545.  
  1546. void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/)
  1547. {
  1548.    TC_LOG_DEBUG("network", "WORLD: CMSG_RESET_INSTANCES");
  1549.  
  1550.    if (Group* group = _player->GetGroup())
  1551.    {
  1552.        if (group->IsLeader(_player->GetGUID()))
  1553.            group->ResetInstances(INSTANCE_RESET_ALL, false, _player);
  1554.    }
  1555.    else
  1556.        _player->ResetInstances(INSTANCE_RESET_ALL, false);
  1557. }
  1558.  
  1559. void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData)
  1560. {
  1561.    TC_LOG_DEBUG("network", "MSG_SET_DUNGEON_DIFFICULTY");
  1562.  
  1563.    uint32 mode;
  1564.    recvData >> mode;
  1565.  
  1566.    if (mode >= MAX_DUNGEON_DIFFICULTY)
  1567.    {
  1568.        TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUID().GetCounter(), mode);
  1569.        return;
  1570.    }
  1571.  
  1572.    if (Difficulty(mode) == _player->GetDungeonDifficulty())
  1573.        return;
  1574.  
  1575.    // cannot reset while in an instance
  1576.    Map* map = _player->FindMap();
  1577.    if (map && map->IsDungeon())
  1578.    {
  1579.        TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player (Name: %s, GUID: %u) tried to reset the instance while player is inside!",
  1580.            _player->GetName().c_str(), _player->GetGUID().GetCounter());
  1581.        return;
  1582.    }
  1583.  
  1584.    Group* group = _player->GetGroup();
  1585.    if (group)
  1586.    {
  1587.        if (group->IsLeader(_player->GetGUID()))
  1588.        {
  1589.            for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
  1590.            {
  1591.                Player* groupGuy = itr->GetSource();
  1592.                if (!groupGuy)
  1593.                    continue;
  1594.  
  1595.                if (!groupGuy->IsInMap(groupGuy))
  1596.                    return;
  1597.  
  1598.                if (groupGuy->GetMap()->IsNonRaidDungeon())
  1599.                {
  1600.                    TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while group member (Name: %s, GUID: %u) is inside!",
  1601.                        _player->GetGUID().GetCounter(), groupGuy->GetName().c_str(), groupGuy->GetGUID().GetCounter());
  1602.                    return;
  1603.                }
  1604.            }
  1605.            // the difficulty is set even if the instances can't be reset
  1606.             //_player->SendDungeonDifficulty(true);
  1607.             group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player);
  1608.             group->SetDungeonDifficulty(Difficulty(mode));
  1609.         }
  1610.     }
  1611.     else
  1612.     {
  1613.         _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false);
  1614.         _player->SetDungeonDifficulty(Difficulty(mode));
  1615.     }
  1616. }
  1617.  
  1618. void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData)
  1619. {
  1620.     TC_LOG_DEBUG("network", "MSG_SET_RAID_DIFFICULTY");
  1621.  
  1622.     uint32 mode;
  1623.     recvData >> mode;
  1624.  
  1625.     if (mode >= MAX_RAID_DIFFICULTY)
  1626.     {
  1627.         TC_LOG_ERROR("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUID().GetCounter(), mode);
  1628.         return;
  1629.     }
  1630.  
  1631.     // cannot reset while in an instance
  1632.     Map* map = _player->FindMap();
  1633.     if (map && map->IsDungeon())
  1634.     {
  1635.         TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUID().GetCounter());
  1636.         return;
  1637.     }
  1638.  
  1639.     if (Difficulty(mode) == _player->GetRaidDifficulty())
  1640.         return;
  1641.  
  1642.     Group* group = _player->GetGroup();
  1643.     if (group)
  1644.     {
  1645.         if (group->IsLeader(_player->GetGUID()))
  1646.         {
  1647.             for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
  1648.             {
  1649.                 Player* groupGuy = itr->GetSource();
  1650.                 if (!groupGuy)
  1651.                     continue;
  1652.  
  1653.                 if (!groupGuy->IsInMap(groupGuy))
  1654.                     return;
  1655.  
  1656.                 if (groupGuy->GetMap()->IsRaid())
  1657.                 {
  1658.                     TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUID().GetCounter());
  1659.                     return;
  1660.                 }
  1661.             }
  1662.             // the difficulty is set even if the instances can't be reset
  1663.            //_player->SendDungeonDifficulty(true);
  1664.            group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, _player);
  1665.            group->SetRaidDifficulty(Difficulty(mode));
  1666.        }
  1667.    }
  1668.    else
  1669.    {
  1670.        _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true);
  1671.        _player->SetRaidDifficulty(Difficulty(mode));
  1672.    }
  1673. }
  1674.  
  1675. void WorldSession::HandleCancelMountAuraOpcode(WorldPacket& /*recvData*/)
  1676. {
  1677.    TC_LOG_DEBUG("network", "WORLD: CMSG_CANCEL_MOUNT_AURA");
  1678.  
  1679.    //If player is not mounted, so go out :)
  1680.    if (!_player->IsMounted())                              // not blizz like; no any messages on blizz
  1681.    {
  1682.        ChatHandler(this).SendSysMessage(LANG_CHAR_NON_MOUNTED);
  1683.        return;
  1684.    }
  1685.  
  1686.    if (_player->IsInFlight())                               // not blizz like; no any messages on blizz
  1687.    {
  1688.        ChatHandler(this).SendSysMessage(LANG_YOU_IN_FLIGHT);
  1689.        return;
  1690.    }
  1691.  
  1692.    _player->RemoveAurasByType(SPELL_AURA_MOUNTED); // Calls Dismount()
  1693. }
  1694.  
  1695. void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData)
  1696. {
  1697.    // fly mode on/off
  1698.    TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
  1699.  
  1700.    ObjectGuid guid;                                            // guid - unused
  1701.    recvData >> guid.ReadAsPacked();
  1702.  
  1703.    recvData.read_skip<uint32>();                          // unk
  1704.  
  1705.    MovementInfo movementInfo;
  1706.    movementInfo.guid = guid;
  1707.    ReadMovementInfo(recvData, &movementInfo);
  1708.  
  1709.    recvData.read_skip<float>();                           // unk2
  1710.  
  1711.    _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
  1712. }
  1713.  
  1714. void WorldSession::HandleRequestPetInfoOpcode(WorldPacket& /*recvData */)
  1715. {
  1716.    /*
  1717.        TC_LOG_DEBUG("network", "WORLD: CMSG_REQUEST_PET_INFO");
  1718.        recvData.hexlike();
  1719.    */
  1720. }
  1721.  
  1722. void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket& recvData)
  1723. {
  1724.    TC_LOG_DEBUG("network", "WORLD: CMSG_SET_TAXI_BENCHMARK_MODE");
  1725.  
  1726.    uint8 mode;
  1727.    recvData >> mode;
  1728.  
  1729.    mode ? _player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK) : _player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK);
  1730.  
  1731.    TC_LOG_DEBUG("network", "Client used \"/timetest %d\" command", mode);
  1732. }
  1733.  
  1734. void WorldSession::HandleQueryInspectAchievements(WorldPacket& recvData)
  1735. {
  1736.    ObjectGuid guid;
  1737.    recvData >> guid.ReadAsPacked();
  1738.  
  1739.    TC_LOG_DEBUG("network", "CMSG_QUERY_INSPECT_ACHIEVEMENTS [%s] Inspected Player [%s]", _player->GetGUID().ToString().c_str(), guid.ToString().c_str());
  1740.    Player* player = ObjectAccessor::FindPlayer(guid);
  1741.    if (!player)
  1742.        return;
  1743.  
  1744.    if (!GetPlayer()->IsWithinDistInMap(player, INSPECT_DISTANCE, false))
  1745.        return;
  1746.  
  1747.    if (GetPlayer()->IsValidAttackTarget(player))
  1748.        return;
  1749.  
  1750.    player->SendRespondInspectAchievements(_player);
  1751. }
  1752.  
  1753. void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recvData*/)
  1754. {
  1755.    // empty opcode
  1756.    TC_LOG_DEBUG("network", "WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE");
  1757.  
  1758.    WorldPacket data(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4);
  1759.    data << uint32(time(NULL));
  1760.    SendPacket(&data);
  1761. }
  1762.  
  1763. void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recvData*/)
  1764. {
  1765.    // empty opcode
  1766.    TC_LOG_DEBUG("network", "WORLD: CMSG_READY_FOR_ACCOUNT_DATA_TIMES");
  1767.  
  1768.    SendAccountDataTimes(GLOBAL_CACHE_MASK);
  1769. }
  1770.  
  1771. void WorldSession::SendSetPhaseShift(uint32 PhaseShift)
  1772. {
  1773.    WorldPacket data(SMSG_SET_PHASE_SHIFT, 4);
  1774.    data << uint32(PhaseShift);
  1775.    SendPacket(&data);
  1776. }
  1777. // Battlefield and Battleground
  1778. void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket& recvData)
  1779. {
  1780.    TC_LOG_DEBUG("network", "WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
  1781.  
  1782.    Battleground* bg = _player->GetBattleground();
  1783.  
  1784.    ObjectGuid guid;
  1785.    recvData >> guid;
  1786.  
  1787.    Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
  1788.    if (!unit)
  1789.        return;
  1790.  
  1791.    if (!unit->IsSpiritService())                            // it's not spirit service
  1792.         return;
  1793.  
  1794.     if (bg)
  1795.         sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, guid);
  1796.  
  1797.     if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetZoneId()))
  1798.         bf->SendAreaSpiritHealerQueryOpcode(_player, guid);
  1799. }
  1800.  
  1801. void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket& recvData)
  1802. {
  1803.     TC_LOG_DEBUG("network", "WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
  1804.  
  1805.     Battleground* bg = _player->GetBattleground();
  1806.  
  1807.     ObjectGuid guid;
  1808.     recvData >> guid;
  1809.  
  1810.     Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
  1811.     if (!unit)
  1812.         return;
  1813.  
  1814.     if (!unit->IsSpiritService())                            // it's not spirit service
  1815.        return;
  1816.  
  1817.    if (bg)
  1818.        bg->AddPlayerToResurrectQueue(guid, _player->GetGUID());
  1819.  
  1820.    if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetZoneId()))
  1821.        bf->AddPlayerToResurrectQueue(guid, _player->GetGUID());
  1822. }
  1823.  
  1824. void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recvData*/)
  1825. {
  1826.    if (_player->IsInFlight())
  1827.        return;
  1828.  
  1829.    if (/*Battlefield* bf = */sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetZoneId()))
  1830.    {
  1831.        // bf->PlayerAskToLeave(_player); FIXME
  1832.        return;
  1833.    }
  1834.  
  1835.    AreaTableEntry const* atEntry = sAreaTableStore.LookupEntry(_player->GetAreaId());
  1836.    if (!atEntry || !(atEntry->flags & AREA_FLAG_WINTERGRASP_2))
  1837.        return;
  1838.  
  1839.    _player->BuildPlayerRepop();
  1840.    _player->ResurrectPlayer(1.0f);
  1841.    _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation());
  1842. }
  1843.  
  1844. void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket)
  1845. {
  1846.    uint8 accept;
  1847.    recvPacket >> accept;
  1848.  
  1849.    if (!_player->HasPendingBind())
  1850.    {
  1851.        TC_LOG_INFO("network", "InstanceLockResponse: Player %s (guid %u) tried to bind himself/teleport to graveyard without a pending bind!",
  1852.            _player->GetName().c_str(), _player->GetGUID().GetCounter());
  1853.        return;
  1854.    }
  1855.  
  1856.    if (accept)
  1857.        _player->BindToInstance();
  1858.    else
  1859.        _player->RepopAtGraveyard();
  1860.  
  1861.    _player->SetPendingBind(0, 0);
  1862. }
  1863.  
  1864. void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
  1865. {
  1866.    TC_LOG_DEBUG("network", "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY");
  1867.  
  1868.    ObjectGuid guid;
  1869.    uint32 spellId;
  1870.    float elevation, speed;
  1871.    float curX, curY, curZ;
  1872.    float targetX, targetY, targetZ;
  1873.    uint8 moveStop;
  1874.  
  1875.    recvPacket >> guid >> spellId >> elevation >> speed;
  1876.    recvPacket >> curX >> curY >> curZ;
  1877.    recvPacket >> targetX >> targetY >> targetZ;
  1878.    recvPacket >> moveStop;
  1879.  
  1880.    Unit* caster = ObjectAccessor::GetUnit(*_player, guid);
  1881.    Spell* spell = caster ? caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) : NULL;
  1882.    if (!spell || spell->m_spellInfo->Id != spellId || !spell->m_targets.HasDst() || !spell->m_targets.HasSrc())
  1883.    {
  1884.        recvPacket.rfinish();
  1885.        return;
  1886.    }
  1887.  
  1888.    Position pos = *spell->m_targets.GetSrcPos();
  1889.    pos.Relocate(curX, curY, curZ);
  1890.    spell->m_targets.ModSrc(pos);
  1891.  
  1892.    pos = *spell->m_targets.GetDstPos();
  1893.    pos.Relocate(targetX, targetY, targetZ);
  1894.    spell->m_targets.ModDst(pos);
  1895.  
  1896.    spell->m_targets.SetElevation(elevation);
  1897.    spell->m_targets.SetSpeed(speed);
  1898.  
  1899.    if (moveStop)
  1900.    {
  1901.        uint32 opcode;
  1902.        recvPacket >> opcode;
  1903.        recvPacket.SetOpcode(opcode);
  1904.        HandleMovementOpcodes(recvPacket);
  1905.    }
  1906. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement