Пример #1
0
void ReputationMgr::SaveToDB()
{
    static SqlStatementID delRep ;
    static SqlStatementID insRep ;

    SqlStatement stmtDel = CharacterDatabase.CreateStatement(delRep, "DELETE FROM character_reputation WHERE guid = ? AND faction=?");
    SqlStatement stmtIns = CharacterDatabase.CreateStatement(insRep, "INSERT INTO character_reputation (guid,faction,standing,flags) VALUES (?, ?, ?, ?)");

    for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr)
    {
        if (itr->second.needSave)
        {
            stmtDel.PExecute(m_player->GetGUIDLow(), itr->second.ID);
            stmtIns.PExecute(m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags);
            itr->second.needSave = false;
        }
    }
}
Пример #2
0
void GuildFinderMgr::SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings)
{
    m_guildSettings[guildGuid] = settings;

    static SqlStatementID replaceGuildFinderSettings;
    SqlStatement stmt = CharacterDatabase.CreateStatement(replaceGuildFinderSettings, "REPLACE INTO guild_finder_guild_settings (guildId, availability, classRoles, interests, level, listed, comment) VALUES(?, ?, ?, ?, ?, ?, ?)");
    stmt.addUInt32(settings.GetGuid());
    stmt.addUInt8(settings.GetAvailability());
    stmt.addUInt8(settings.GetClassRoles());
    stmt.addUInt8(settings.GetInterests());
    stmt.addUInt8(settings.GetLevel());
    stmt.addUInt8(settings.IsListed());
    stmt.addString(settings.GetComment());
    stmt.Execute();
}
Пример #3
0
void GuildFinderMgr::DeleteGuild(uint32 guildId)
{
    std::vector<MembershipRequest>::iterator itr = m_membershipRequests[guildId].begin();
    while (itr != m_membershipRequests[guildId].end())
    {
        uint32 applicant = itr->GetPlayerGuid();

        CharacterDatabase.BeginTransaction();

        static SqlStatementID deleteFinderApplicant;
        static SqlStatementID deleteGuildFinderSettings;
        SqlStatement stmt = CharacterDatabase.CreateStatement(deleteFinderApplicant, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?");
        stmt.addUInt32(itr->GetGuildId());
        stmt.addUInt32(itr->GetPlayerGuid());
        stmt.Execute();

        SqlStatement stmt2 = CharacterDatabase.CreateStatement(deleteGuildFinderSettings, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?");
        stmt2.addUInt32(itr->GetGuildId());
        stmt2.Execute();

        CharacterDatabase.CommitTransaction();

        m_membershipRequests[guildId].erase(itr);

        // Notify the applicant his submition has been removed
        if (Player* player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, applicant)))
            SendMembershipRequestListUpdate(*player);
    }

    m_membershipRequests.erase(guildId);
    m_guildSettings.erase(guildId);

    // Notify the guild master the list changed (even if he's not a GM any more, not sure if needed)
    if (Guild* guild = sGuildMgr.GetGuildById(guildId))
        SendApplicantListUpdate(*guild);
}
Пример #4
0
void MapPersistentState::SaveGORespawnTime(uint32 loguid, time_t t)
{
    SetGORespawnTime(loguid, t);

    // BGs/Arenas always reset at server restart/unload, so no reason store in DB
    if (GetMapEntry()->IsBattleGroundOrArena())
        return;

    CharacterDatabase.BeginTransaction();

    static SqlStatementID delSpawnTime ;
    static SqlStatementID insSpawnTime ;

    SqlStatement stmt = CharacterDatabase.CreateStatement(delSpawnTime, "DELETE FROM gameobject_respawn WHERE guid = ? AND instance = ?");
    stmt.PExecute(loguid, m_instanceid);

    if (t > sWorld.GetGameTime())
    {
        stmt = CharacterDatabase.CreateStatement(insSpawnTime, "INSERT INTO gameobject_respawn VALUES ( ?, ?, ? )");
        stmt.PExecute(loguid, uint64(t), m_instanceid);
    }

    CharacterDatabase.CommitTransaction();
}
Пример #5
0
void Antispam::applySanction(MessageBlock& messageBlock, uint32 detectType, uint32 repeats)
{
    auto chatType = std::to_string(messageBlock.type);

    switch (detectType)
    {
        case DETECT_STANDARD:
            logSpam(messageBlock, "DETECT_STANDARD, chatType " + chatType);
            break;
        case DETECT_SEPARATED:
            logSpam(messageBlock, "DETECT_SEPARATED, chatType " + chatType);
            break;
        case DETECT_FLOOD:
            std::string reason = "DETECT_FLOOD, " + std::to_string(repeats) + " repeats, chatType " + chatType;
            logSpam(messageBlock, reason);
            break;
    }

    mute(messageBlock.fromAccount);
    ChannelMgr::AnnounceBothFactionsChannel("ChatSpam", messageBlock.fromGuid, messageBlock.msg.c_str());

    static SqlStatementID insDetect;
    SqlStatement stmt = LoginDatabase.CreateStatement(insDetect, "INSERT INTO `antispam_detected` VALUES (?, 1, ?, ?) "
        "ON DUPLICATE KEY UPDATE `detectScore` = `detectScore` + 1, `detectTime` = ?, `unmuteTime` = ?");
    time_t currentTime = time(nullptr);
    time_t unmuteTime = currentTime + m_mutetime;
    stmt.addUInt32(messageBlock.fromAccount);
    stmt.addUInt64(currentTime);
    stmt.addUInt64(unmuteTime);
    stmt.addUInt64(currentTime);
    stmt.addUInt64(unmuteTime);
    stmt.DirectExecute();

    QueryResult *result = LoginDatabase.PQuery("SELECT `detectScore` FROM `antispam_detected` WHERE `id` = %u", messageBlock.fromAccount);
    if (result)
    {
        auto fields = result->Fetch();
        if (fields[0].GetUInt8() >= m_detectThreshold)
        {
            logSpam(messageBlock, "BAN SANCTION");
            if (m_banEnabled)
            {
                sWorld.BanAccount(messageBlock.fromAccount, 0, "Spam detect. See details in logs", "Antispam");
                LoginDatabase.PExecute("DELETE FROM `antispam_detected` WHERE `id` = %u", messageBlock.fromAccount);
            }
        }
        delete result;
    }
}
Пример #6
0
void Antispam::logSpam(MessageBlock& messageBlock, std::string const& reason)
{
    if (!LogsDatabase || !sWorld.getConfig(CONFIG_BOOL_LOGSDB_CHAT))
        return;

    static SqlStatementID insLogSpam;
    SqlStatement logStmt = LogsDatabase.CreateStatement(insLogSpam,
        "INSERT INTO logs_spamdetect SET accountId=?, guid=?, message=?, reason=?");
    logStmt.addUInt32(messageBlock.fromAccount);
    logStmt.addUInt32(messageBlock.fromGuid.GetCounter());
    logStmt.addString(messageBlock.msg);
    logStmt.addString(reason);
    logStmt.Execute();
}
Пример #7
0
void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResultAutoPtr result, uint32 accountId, std::string newname)
{
    WorldSession * session = sWorld.FindSession(accountId);
    if (!session)
        return;

    if (!result)
    {
        WorldPacket data(SMSG_CHAR_RENAME, 1);
        data << uint8(CHAR_CREATE_ERROR);
        session->SendPacket(&data);
        return;
    }

    uint32 guidLow = result->Fetch()[0].GetUInt32();
    uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
    std::string oldname = result->Fetch()[1].GetCppString();

    static SqlStatementID changeCharName;
    static SqlStatementID deleteDeclinedName;

    RealmDataDatabase.BeginTransaction();

    SqlStatement stmt = RealmDataDatabase.CreateStatement(changeCharName, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?");
    stmt.addString(newname);
    stmt.addUInt32(uint32(AT_LOGIN_RENAME));
    stmt.addUInt32(guidLow);
    stmt.Execute();

    stmt = RealmDataDatabase.CreateStatement(deleteDeclinedName, "DELETE FROM character_declinedname WHERE guid = ?");
    stmt.PExecute(guidLow);

    RealmDataDatabase.CommitTransaction();

    sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->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;
    session->SendPacket(&data);
}
Пример #8
0
void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::string data)
{
    if ((1 << type) & GLOBAL_CACHE_MASK)
    {
        uint32 acc = GetAccountId();

        static SqlStatementID delId;
        static SqlStatementID insId;

        CharacterDatabase.BeginTransaction ();

        SqlStatement stmt = CharacterDatabase.CreateStatement(delId, "DELETE FROM account_data WHERE account=? AND type=?");
        stmt.PExecute(acc, uint32(type));

        stmt = CharacterDatabase.CreateStatement(insId, "INSERT INTO account_data VALUES (?,?,?,?)");
        stmt.PExecute(acc, uint32(type), uint64(time_), data.c_str());

        CharacterDatabase.CommitTransaction ();
    }
    else
    {
        // _player can be NULL and packet received after logout but m_GUID still store correct guid
        if(!m_GUIDLow)
            return;

        static SqlStatementID delId;
        static SqlStatementID insId;

        CharacterDatabase.BeginTransaction ();

        SqlStatement stmt = CharacterDatabase.CreateStatement(delId, "DELETE FROM character_account_data WHERE guid=? AND type=?");
        stmt.PExecute(m_GUIDLow, uint32(type));

        stmt = CharacterDatabase.CreateStatement(insId, "INSERT INTO character_account_data VALUES (?,?,?,?)");
        stmt.PExecute(m_GUIDLow, uint32(type), uint64(time_), data.c_str());

        CharacterDatabase.CommitTransaction ();
    }

    m_accountData[type].Time = time_;
    m_accountData[type].Data = data;
}
Пример #9
0
int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
    // NOTE: ATM the socket is singlethread, have this in mind ...
    uint8 digest[20];
    uint32 clientSeed, id, security;
    uint32 unk2;
    uint32 BuiltNumberClient;
    uint8 expansion = 0;
    uint8 xp_rate = 0;
    LocaleConstant locale;
    std::string account;
    Sha1Hash sha1;
    BigNumber v, s, g, N, K;
    WorldPacket packet, SendAddonPacked;

    // Read the content of the packet
    recvPacket >> BuiltNumberClient;
    recvPacket >> unk2;
    recvPacket >> account;
    recvPacket >> clientSeed;
    recvPacket.read(digest, 20);

    DEBUG_LOG("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u",
              BuiltNumberClient,
              unk2,
              account.c_str(),
              clientSeed);

    // Check the version of client trying to connect
    if (!IsAcceptableClientBuild(BuiltNumberClient))
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_VERSION_MISMATCH);

        SendPacket(packet);

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch).");
        return -1;
    }

    // Get the account information from the realmd database
    std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
    LoginDatabase.escape_string(safe_account);
    // No SQL injection, username escaped.

    QueryResult* result =
        LoginDatabase.PQuery("SELECT "
                             "id, "                      //0
                             "gmlevel, "                 //1
                             "sessionkey, "              //2
                             "last_ip, "                 //3
                             "locked, "                  //4
                             "v, "                       //5
                             "s, "                       //6
                             "expansion, "               //7
                             "mutetime, "                //8
                             "locale, "                  //9
                             "os "                       //10
                             "FROM account "
                             "WHERE username = '******'",
                             safe_account.c_str());

    // Stop if the account is not found
    if (!result)
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_UNKNOWN_ACCOUNT);

        SendPacket(packet);

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
        return -1;
    }

    Field* fields = result->Fetch();

    expansion = ((sWorld.getConfig(CONFIG_UINT32_EXPANSION) > fields[7].GetUInt8()) ? fields[7].GetUInt8() : sWorld.getConfig(CONFIG_UINT32_EXPANSION));

    N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
    g.SetDword(7);

    v.SetHexStr(fields[5].GetString());
    s.SetHexStr(fields[6].GetString());

    const char* sStr = s.AsHexStr();                        // Must be freed by OPENSSL_free()
    const char* vStr = v.AsHexStr();                        // Must be freed by OPENSSL_free()

    DEBUG_LOG("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s",
              sStr,
              vStr);

    OPENSSL_free((void*) sStr);
    OPENSSL_free((void*) vStr);

    ///- Re-check ip locking (same check as in realmd).
    if (fields[4].GetUInt8() == 1)  // if ip is locked
    {
        if (strcmp(fields[3].GetString(), GetRemoteAddress().c_str()))
        {
            packet.Initialize(SMSG_AUTH_RESPONSE, 1);
            packet << uint8(AUTH_FAILED);
            SendPacket(packet);

            delete result;
            BASIC_LOG("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs).");
            return -1;
        }
    }

    id = fields[0].GetUInt32();
    security = fields[1].GetUInt16();
    if (security > SEC_ADMINISTRATOR)                       // prevent invalid security settings in DB
        security = SEC_ADMINISTRATOR;

    K.SetHexStr(fields[2].GetString());

    time_t mutetime = time_t (fields[8].GetUInt64());

    locale = LocaleConstant(fields[9].GetUInt8());
    if (locale >= MAX_LOCALE)
        locale = LOCALE_enUS;

    std::string os = fields[10].GetString();

    delete result;

    // Re-check account ban (same check as in realmd)
    QueryResult* banresult =
        LoginDatabase.PQuery("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)"
                             "UNION "
                             "SELECT 1 FROM ip_banned WHERE (unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'",
                             id, GetRemoteAddress().c_str());

    if (banresult) // if account banned
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_BANNED);
        SendPacket(packet);

        delete banresult;

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
        return -1;
    }

    // Check for custom xp rate
    QueryResult* customXpResult = CharacterDatabase.PQuery ("SELECT xp_rate FROM account_xp_rates WHERE id = '%u'", id);
    if (customXpResult)
    {
        Field* xpFields = customXpResult->Fetch();
        xp_rate = xpFields[0].GetUInt8();
    }

    // Check locked state for server
    AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit();

    if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType)
    {
        WorldPacket Packet(SMSG_AUTH_RESPONSE, 1);
        Packet << uint8(AUTH_UNAVAILABLE);

        SendPacket(packet);

        BASIC_LOG("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
        return -1;
    }

    // Check that Key and account name are the same on client and server
    Sha1Hash sha;

    uint32 t = 0;
    uint32 seed = m_Seed;

    sha.UpdateData(account);
    sha.UpdateData((uint8*) & t, 4);
    sha.UpdateData((uint8*) & clientSeed, 4);
    sha.UpdateData((uint8*) & seed, 4);
    sha.UpdateBigNumbers(&K, NULL);
    sha.Finalize();

    if (memcmp(sha.GetDigest(), digest, 20))
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_FAILED);

        SendPacket(packet);

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed).");
        return -1;
    }

    std::string address = GetRemoteAddress();

    DEBUG_LOG("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
              account.c_str(),
              address.c_str());

    // Update the last_ip in the database
    // No SQL injection, username escaped.
    static SqlStatementID updAccount;

    SqlStatement stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET last_ip = ? WHERE username = ?");
    stmt.PExecute(address.c_str(), account.c_str());

    // NOTE ATM the socket is single-threaded, have this in mind ...
    ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, xp_rate, mutetime, locale), -1);

    m_Crypt.Init(&K);

    m_Session->LoadTutorialsData();
    m_Session->InitWarden(&K, os);

    // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec
    ACE_OS::sleep(ACE_Time_Value(0, 10000));

    sWorld.AddSession(m_Session);

    // Create and send the Addon packet
    if (sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked))
        SendPacket(SendAddonPacked);

    return 0;
}
Пример #10
0
void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder)
{
    ObjectGuid playerGuid = holder->GetGuid();

    Player *pCurrChar = new Player(this);
    pCurrChar->GetMotionMaster()->Initialize();

    // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools)
    if(!pCurrChar->LoadFromDB(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;
    }

    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->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK);
    SendAccountDataTimes(PER_CHARACTER_CACHE_MASK);

    data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2);         // added in 2.2.0
    data << uint8(2);                                       // unknown value
    data << uint8(0);                                       // enable(1)/disable(0) voice chat interface in client
    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 );
        DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" );
    }

    //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow());
    QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD);

    if(resultGuild)
    {
        Field *fields = resultGuild->Fetch();
        pCurrChar->SetInGuild(fields[0].GetUInt32());
        pCurrChar->SetRank(fields[1].GetUInt32());
        delete resultGuild;
    }
    else if(pCurrChar->GetGuildId())                        // clear guild related fields in case wrong data about nonexistent membership
    {
        pCurrChar->SetInGuild(0);
        pCurrChar->SetRank(0);
    }

    if(pCurrChar->GetGuildId() != 0)
    {
        Guild* guild = sGuildMgr.GetGuildById(pCurrChar->GetGuildId());
        if(guild)
        {
            data.Initialize(SMSG_GUILD_EVENT, (1+1+guild->GetMOTD().size()+1));
            data << uint8(GE_MOTD);
            data << uint8(1);
            data << guild->GetMOTD();
            SendPacket(&data);
            DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" );

            guild->DisplayGuildBankTabsInfo(this);

            guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetObjectGuid(), pCurrChar->GetName());
        }
        else
        {
            // remove wrong guild data
            sLog.outError("Player %s (GUID: %u) marked as member of nonexistent 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);
        }
    }

    if (!pCurrChar->GetMap()->Add(pCurrChar))
    {
        // normal delayed teleport protection not applied (and this correct) for this case (Player object just created)
        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->TeleportToHomebind();
    }

    sObjectAccessor.AddObject(pCurrChar);
    //DEBUG_LOG("Player %s added to Map.",pCurrChar->GetName());

    pCurrChar->SendInitialPacketsAfterAddToMap();

    static SqlStatementID updChars;
    static SqlStatementID updAccount;

    SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 1 WHERE guid = ?");
    stmt.PExecute(pCurrChar->GetGUIDLow());

    stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET active_realm_id = ? WHERE id = ?");
    stmt.PExecute(realmID, GetAccountId());

    pCurrChar->SetInGameTime( WorldTimer::getMSTime() );

    // announce group about member online (must be after add to player list to receive announce to self)
    if (Group *group = pCurrChar->GetGroup())
        group->SendUpdate();

    // friend status
    sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetObjectGuid(), 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);   // 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);        // 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->SetFFAPvP(true);

    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,true);
        pCurrChar->SendTalentsInfoData(false);              // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
        SendNotification(LANG_RESET_TALENTS);               // we can use SMSG_TALENTS_INVOLUNTARILY_RESET here
    }

    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
        pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);

    // show time before shutdown if shutdown planned.
    if (sWorld.IsShutdowning())
        sWorld.ShutdownMsg(true,pCurrChar);

    if (sWorld.getConfig(CONFIG_BOOL_ALL_TAXI_PATHS))
        pCurrChar->SetTaxiCheater(true);

    if (pCurrChar->isGameMaster())
        SendNotification(LANG_GM_ON);

    if (!pCurrChar->isGMVisible())
        SendNotification(LANG_INVISIBLE_INVISIBLE);

    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;

    // Handle Login-Achievements (should be handled after loading)
    pCurrChar->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN, 1);

    delete holder;
}
Пример #11
0
/// %Log the player out
void WorldSession::LogoutPlayer(bool Save)
{
    // finish pending transfers before starting the logout
    while(_player && _player->IsBeingTeleportedFar())
        HandleMoveWorldportAckOpcode();

    m_playerLogout = true;
    m_playerSave = Save;

    if (_player)
    {
        // Playerbot mod: log out all player bots owned by this toon
        if (GetPlayer()->GetPlayerbotMgr())
            GetPlayer()->GetPlayerbotMgr()->LogoutAllBots();

        sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (guid: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow());

        if (ObjectGuid lootGuid = GetPlayer()->GetLootGuid())
            DoLootRelease(lootGuid);

        ///- If the player just died before logging out, make him appear as a ghost
        //FIXME: logout must be delayed in case lost connection with client in time of combat
        if (_player->GetDeathTimer())
        {
            _player->getHostileRefManager().deleteReferences();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();
        }
        else if (!_player->getAttackers().empty())
        {
            _player->CombatStop();
            _player->getHostileRefManager().setOnlineOfflineState(false);
            _player->RemoveAllAurasOnDeath();

            // build set of player who attack _player or who have pet attacking of _player
            std::set<Player*> aset;
            for(Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr)
            {
                Unit* owner = (*itr)->GetOwner();           // including player controlled case
                if(owner)
                {
                    if(owner->GetTypeId()==TYPEID_PLAYER)
                        aset.insert((Player*)owner);
                }
                else if((*itr)->GetTypeId()==TYPEID_PLAYER)
                    aset.insert((Player*)(*itr));
            }

            _player->SetPvPDeath(!aset.empty());
            _player->KillPlayer();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();

            // give honor to all attackers from set like group case
            for(std::set<Player*>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr)
                (*itr)->RewardHonor(_player,aset.size());

            // give bg rewards and update counters like kill by first from attackers
            // this can't be called for all attackers.
            if(!aset.empty())
                if(BattleGround *bg = _player->GetBattleGround())
                    bg->HandleKillPlayer(_player,*aset.begin());
        }
        else if(_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
        {
            // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION
            _player->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
            //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time
            _player->KillPlayer();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();
        }
        else if (_player->HasPendingBind())
        {
            _player->RepopAtGraveyard();
            _player->SetPendingBind(NULL, 0);
        }

        //drop a flag if player is carrying it
        if(BattleGround *bg = _player->GetBattleGround())
            bg->EventPlayerLoggedOut(_player);

        ///- Teleport to home if the player is in an invalid instance
        if(!_player->m_InstanceValid && !_player->isGameMaster())
        {
            _player->TeleportToHomebind();
            //this is a bad place to call for far teleport because we need player to be in world for successful logout
            //maybe we should implement delayed far teleport logout?
        }

        // FG: finish pending transfers after starting the logout
        // this should fix players beeing able to logout and login back with full hp at death position
        while(_player->IsBeingTeleportedFar())
            HandleMoveWorldportAckOpcode();

        for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
        {
            if(BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i))
            {
                _player->RemoveBattleGroundQueueId(bgQueueTypeId);
                sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetObjectGuid(), true);
            }
        }

        ///- Reset the online field in the account table
        // no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage
        // No SQL injection as AccountID is uint32
        if (!GetPlayer()->GetPlayerbotAI())
        {
            static SqlStatementID id;

            SqlStatement stmt = LoginDatabase.CreateStatement(id, "UPDATE account SET active_realm_id = ? WHERE id = ?");
            stmt.PExecute(uint32(0), GetAccountId());
        }

        ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
        if (Guild* guild = sGuildMgr.GetGuildById(_player->GetGuildId()))
        {
            if (MemberSlot* slot = guild->GetMemberSlot(_player->GetObjectGuid()))
            {
                slot->SetMemberStats(_player);
                slot->UpdateLogoutTime();
            }

            guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetObjectGuid(), _player->GetName());
        }

        ///- Remove pet
        _player->RemovePet(PET_SAVE_AS_CURRENT);

        _player->InterruptNonMeleeSpells(true);

        ///- empty buyback items and save the player in the database
        // some save parts only correctly work in case player present in map/player_lists (pets, etc)
        if(Save)
            _player->SaveToDB();

        ///- Leave all channels before player delete...
        _player->CleanupChannels();

        // LFG cleanup
        sLFGMgr.Leave(_player);

        ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
        _player->UninviteFromGroup();

        // remove player from the group if he is:
        // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
        if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
            _player->RemoveFromGroup();

        ///- Send update to group
        if(_player->GetGroup())
            _player->GetGroup()->SendUpdate();

        ///- Broadcast a logout message to the player's friends
        sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetObjectGuid(), true);
        sSocialMgr.RemovePlayerSocial (_player->GetGUIDLow ());

        // Playerbot - remember player GUID for update SQL below
        uint32 guid = GetPlayer()->GetGUIDLow();

        ///- Remove the player from the world
        // the player may not be in the world when logging out
        // e.g if he got disconnected during a transfer to another map
        // calls to GetMap in this case may cause crashes
        if (_player->IsInWorld())
        {
            Map* _map = _player->GetMap();
            _map->Remove(_player, true);
        }
        else
        {
            _player->CleanupsBeforeDelete();
            Map::DeleteFromWorld(_player);
        }

        SetPlayer(NULL);                                    // deleted in Remove/DeleteFromWorld call

        ///- Send the 'logout complete' packet to the client
        WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 );
        SendPacket( &data );

        static SqlStatementID updChars;

        // Playerbot mod: commented out above and do this one instead
        SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 0 WHERE guid = ?");
        stmt.PExecute(guid);

        DEBUG_LOG( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" );
    }

    m_playerLogout = false;
    m_playerSave = false;
    m_playerRecentlyLogout = true;
    LogoutRequest(0);
}
Пример #12
0
dmlpackage::CalpontDMLPackage* CalpontDMLFactory::makeCalpontDMLPackage(dmlpackage::VendorDMLStatement& vpackage,
        std::string defaultSchema /*= ""*/)
{
    CalpontDMLPackage* packagePtr = 0;
    try
    {
        std::string dmlStatement = vpackage.get_DMLStatement();
		//@Bug 2680. DMLParser is not thread safe.
		boost::mutex::scoped_lock lk(fParserLock);
        DMLParser parser;
        if (defaultSchema.size())
		{
            parser.setDefaultSchema(defaultSchema);
		}
        parser.parse(dmlStatement.c_str());
		
        if (parser.good())
        {

            const ParseTree &ptree = parser.getParseTree();
            SqlStatement* statementPtr = ptree[0];

            int dmlStatementType = statementPtr->getStatementType();

            switch (dmlStatementType)
            {
                case DML_INSERT:
                    packagePtr = new InsertDMLPackage(statementPtr->getSchemaName(), statementPtr->getTableName(),
                                                      ptree.fSqlText, vpackage.get_SessionID() );
		    packagePtr->set_SQLStatement(dmlStatement);
                    (void)packagePtr->buildFromSqlStatement(*statementPtr);
                    break;

                case DML_UPDATE:
                    packagePtr = new UpdateDMLPackage(statementPtr->getSchemaName(), statementPtr->getTableName(),
                                                      ptree.fSqlText, vpackage.get_SessionID() );
		    packagePtr->set_SQLStatement(dmlStatement);
                    (void)packagePtr->buildFromSqlStatement(*statementPtr);
                    break;

                case DML_DELETE:
                    packagePtr = new DeleteDMLPackage(statementPtr->getSchemaName(), statementPtr->getTableName(),
                                                      ptree.fSqlText, vpackage.get_SessionID() );
		    packagePtr->set_SQLStatement(dmlStatement);
                    (void)packagePtr->buildFromSqlStatement(*statementPtr);
                    break;

                case DML_COMMAND:
                    packagePtr = new CommandDMLPackage(ptree.fSqlText, vpackage.get_SessionID());
                    (void)packagePtr->buildFromSqlStatement(*statementPtr);
                    break;

                default:
                    cerr << "makeCalpontDMLPackage: invalid statement type" << endl;
                    break;

            }

        }
    }
    catch (std::exception& ex)
    {
        cerr << "makeCalpontDMLPackage:" << ex.what() << endl;
    }
    catch (...)
    {
        cerr << "makeCalpontDMLPackage: caught unknown exception!" << endl;
    }

    return packagePtr;

}
Пример #13
0
/// %Log the player out
void WorldSession::LogoutPlayer(bool Save)
{
    // finish pending transfers before starting the logout
    while (_player && _player->IsBeingTeleportedFar())
        HandleMoveWorldportAckOpcode();

    m_playerLogout = true;
    m_playerSave = Save;

    if (_player)
    {
#ifdef BUILD_PLAYERBOT
        // Log out all player bots owned by this toon
        if (_player->GetPlayerbotMgr())
            _player->GetPlayerbotMgr()->LogoutAllBots();
#endif

        sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (guid: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName(), _player->GetGUIDLow());

        if (Loot* loot = sLootMgr.GetLoot(_player))
            loot->Release(_player);

        if (_player->GetDeathTimer())
        {
            _player->getHostileRefManager().deleteReferences();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();
        }
        else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
        {
            // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION
            _player->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
            //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time
            _player->KillPlayer();
            _player->BuildPlayerRepop();
            _player->RepopAtGraveyard();
        }
        else if (_player->isInCombat())
            _player->CombatStop(true, true);

        // drop a flag if player is carrying it
        if (BattleGround* bg = _player->GetBattleGround())
            bg->EventPlayerLoggedOut(_player);

        ///- Teleport to home if the player is in an invalid instance
        if (!_player->m_InstanceValid && !_player->isGameMaster())
        {
            _player->TeleportToHomebind();
            // this is a bad place to call for far teleport because we need player to be in world for successful logout
            // maybe we should implement delayed far teleport logout?
        }

        // FG: finish pending transfers after starting the logout
        // this should fix players beeing able to logout and login back with full hp at death position
        while (_player->IsBeingTeleportedFar())
            HandleMoveWorldportAckOpcode();

        for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
        {
            if (BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i))
            {
                _player->RemoveBattleGroundQueueId(bgQueueTypeId);
                sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetObjectGuid(), true);
            }
        }

        ///- Reset the online field in the account table
        // no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage
        // No SQL injection as AccountID is uint32
        static SqlStatementID id;

#ifdef BUILD_PLAYERBOT
        if (!_player->GetPlayerbotAI())
        {
            // Unmodded core code below
            SqlStatement stmt = LoginDatabase.CreateStatement(id, "UPDATE account SET active_realm_id = ? WHERE id = ?");
            stmt.PExecute(uint32(0), GetAccountId());
        }
#else
        SqlStatement stmt = LoginDatabase.CreateStatement(id, "UPDATE account SET active_realm_id = ? WHERE id = ?");
        stmt.PExecute(uint32(0), GetAccountId());
#endif

        ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
        if (Guild* guild = sGuildMgr.GetGuildById(_player->GetGuildId()))
        {
            if (MemberSlot* slot = guild->GetMemberSlot(_player->GetObjectGuid()))
            {
                slot->SetMemberStats(_player);
                slot->UpdateLogoutTime();
            }

            guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetObjectGuid(), _player->GetName());
        }

        ///- Remove pet
        _player->RemovePet(PET_SAVE_AS_CURRENT);

        ///- empty buyback items and save the player in the database
        // some save parts only correctly work in case player present in map/player_lists (pets, etc)
        if (Save)
            _player->SaveToDB();

        ///- Leave all channels before player delete...
        _player->CleanupChannels();

        ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
        _player->UninviteFromGroup();

        // remove player from the group if he is:
        // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
        if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket && !m_Socket->IsClosed())
            _player->RemoveFromGroup();

        ///- Send update to group
        if (Group* group = _player->GetGroup())
            group->UpdatePlayerOnlineStatus(_player, false);

        ///- Broadcast a logout message to the player's friends
        sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetObjectGuid(), true);
        sSocialMgr.RemovePlayerSocial(_player->GetGUIDLow());

#ifdef BUILD_PLAYERBOT
        // Remember player GUID for update SQL below
        uint32 guid = _player->GetGUIDLow();
#endif

        ///- Remove the player from the world
        // the player may not be in the world when logging out
        // e.g if he got disconnected during a transfer to another map
        // calls to GetMap in this case may cause crashes
        if (_player->IsInWorld())
        {
            Map* _map = _player->GetMap();
            _map->Remove(_player, true);
        }
        else
        {
            _player->CleanupsBeforeDelete();
            Map::DeleteFromWorld(_player);
        }

        SetPlayer(nullptr);                                    // deleted in Remove/DeleteFromWorld call

        ///- Send the 'logout complete' packet to the client
        WorldPacket data(SMSG_LOGOUT_COMPLETE, 0);
        SendPacket(data);

        static SqlStatementID updChars;

#ifdef BUILD_PLAYERBOT
        // Set for only character instead of accountid
        // Different characters can be alive as bots
        SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 0 WHERE guid = ?");
        stmt.PExecute(guid);
#else
        ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline
        // No SQL injection as AccountId is uint32
        stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 0 WHERE account = ?");
        stmt.PExecute(GetAccountId());
#endif

        DEBUG_LOG("SESSION: Sent SMSG_LOGOUT_COMPLETE Message");
    }

    m_playerLogout = false;
    m_playerSave = false;
    m_playerRecentlyLogout = true;
    LogoutRequest(0);
}
Пример #14
0
bool Item::LoadFromDB(uint32 guidLow, Field* fields, ObjectGuid ownerGuid)
{
    // create item before any checks for store correct guid
    // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
    Object::_Create(ObjectGuid(HIGHGUID_ITEM, guidLow));

    if (!LoadValues(fields[0].GetString()))
    {
        sLog.outError("Item::LoadFromDB: %s have broken data in `data` field. Can't be loaded.", GetGuidStr().c_str());
        return false;
    }

    SetText(fields[1].GetCppString());

    bool needSave = false;                                  // need explicit save data at load fixes

    // overwrite possible wrong/corrupted guid
    ObjectGuid new_item_guid = ObjectGuid(HIGHGUID_ITEM, guidLow);
    if (GetGuidValue(OBJECT_FIELD_GUID) != new_item_guid)
    {
        SetGuidValue(OBJECT_FIELD_GUID, new_item_guid);
        needSave = true;
    }

    ItemPrototype const* proto = GetProto();
    if (!proto)
        return false;

    // update max durability (and durability) if need
    if (proto->MaxDurability != GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
    {
        SetUInt32Value(ITEM_FIELD_MAXDURABILITY, proto->MaxDurability);
        if (GetUInt32Value(ITEM_FIELD_DURABILITY) > proto->MaxDurability)
            SetUInt32Value(ITEM_FIELD_DURABILITY, proto->MaxDurability);

        needSave = true;
    }

    // recalculate suffix factor
    if (GetItemRandomPropertyId() < 0)
    {
        if (UpdateItemSuffixFactor())
            needSave = true;
    }

    // Remove bind flag for items vs NO_BIND set
    if (IsSoulBound() && proto->Bonding == NO_BIND)
    {
        ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_BINDED, false);
        needSave = true;
    }

    // update duration if need, and remove if not need
    if ((proto->Duration == 0) != (GetUInt32Value(ITEM_FIELD_DURATION) == 0))
    {
        SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration);
        needSave = true;
    }

    // set correct owner
    if (ownerGuid && GetOwnerGuid() != ownerGuid)
    {
        SetOwnerGuid(ownerGuid);
        needSave = true;
    }

    // set correct wrapped state
    if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
    {
        // wrapped item must be wrapper (used version that not stackable)
        if (!(proto->Flags & ITEM_FLAG_WRAPPER) || GetMaxStackCount() > 1)
        {
            RemoveFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED);
            needSave = true;

            // also cleanup for sure gift table
            DeleteGiftsFromDB();
        }
    }

    if (needSave)                                          // normal item changed state set not work at loading
    {
        std::ostringstream ss;
        for (uint16 i = 0; i < m_valuesCount; ++i)
            ss << GetUInt32Value(i) << " ";

        static SqlStatementID updItem;
        SqlStatement stmt = CharacterDatabase.CreateStatement(updItem, "UPDATE item_instance SET owner_guid = ?, data = ? WHERE guid = ?");
        stmt.PExecute(GetOwnerGuid().GetCounter(), ss.str().c_str(), guidLow);
    }

    return true;
}
Пример #15
0
void Item::DeleteFromInventoryDB(uint32 guidLow)
{
    static SqlStatementID delInv;
    SqlStatement stmt = CharacterDatabase.CreateStatement(delInv, "DELETE FROM character_inventory WHERE item = ?");
    stmt.PExecute(guidLow);
}
Пример #16
0
void Item::DeleteSoulboundTradeableFromDB()
{
    static SqlStatementID delData;
    SqlStatement stmt = CharacterDatabase.CreateStatement(delData, "DELETE FROM item_soulbound_trade_data WHERE itemGuid = ?");
    stmt.PExecute(GetGUIDLow());
}
Пример #17
0
void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
    ObjectGuid playerGuid = holder->GetGuid();

    Player* pCurrChar = new Player(this);
    pCurrChar->GetMotionMaster()->Initialize();
    SetPlayer(pCurrChar);
    m_playerLoading = true;

    SetOnline();

    // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools)
    if (!pCurrChar->LoadFromDB(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;

        sLog.outError("HandlePlayerLogin> LoadFromDB failed to load %s, AccountId = %u", pCurrChar->GetGuidStr().c_str(), GetAccountId());

        WorldPacket data(SMSG_CHARACTER_LOGIN_FAILED, 1);
        data << (uint8)CHAR_LOGIN_NO_CHARACTER;
        SendPacket(data, true);
        return;
    }

    WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20);
    data << pCurrChar->GetMapId();
    data << pCurrChar->GetPositionX();
    data << pCurrChar->GetPositionY();
    data << pCurrChar->GetPositionZ();
    data << pCurrChar->GetOrientation();
    SendPacket(data);

    data.Initialize(SMSG_ACCOUNT_DATA_TIMES, 128);
    for (int i = 0; i < 32; ++i)
        data << uint32(0);
    SendPacket(data);

    // Send Spam records
    SendExpectedSpamRecords();
    SendMotd(pCurrChar);

    // QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow());
    QueryResult* resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD);

    if (resultGuild)
    {
        Field* fields = resultGuild->Fetch();
        pCurrChar->SetInGuild(fields[0].GetUInt32());
        pCurrChar->SetRank(fields[1].GetUInt32());
        delete resultGuild;
    }
    else if (pCurrChar->GetGuildId())                       // clear guild related fields in case wrong data about nonexistent membership
    {
        pCurrChar->SetInGuild(0);
        pCurrChar->SetRank(0);
    }

    if (pCurrChar->GetGuildId() != 0)
    {
        Guild* guild = sGuildMgr.GetGuildById(pCurrChar->GetGuildId());
        if (guild)
        {
            data.Initialize(SMSG_GUILD_EVENT, (1 + 1 + guild->GetMOTD().size() + 1));
            data << uint8(GE_MOTD);
            data << uint8(1);
            data << guild->GetMOTD();
            SendPacket(data);
            DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)");

            guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetObjectGuid(), pCurrChar->GetName());
        }
        else
        {
            // remove wrong guild data
            sLog.outError("Player %s (GUID: %u) marked as member of nonexistent guild (id: %u), removing guild membership for player.", pCurrChar->GetName(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
            pCurrChar->SetInGuild(0);
        }
    }

    if (!pCurrChar->isAlive())
        pCurrChar->SendCorpseReclaimDelay(true);

    pCurrChar->SendInitialPacketsBeforeAddToMap();

    // Show cinematic at the first time that player login
    if (!pCurrChar->getCinematic())
    {
        pCurrChar->setCinematic(1);

        if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()))
            pCurrChar->SendCinematicStart(rEntry->CinematicSequence);
    }

    uint32 miscRequirement = 0;
    AreaLockStatus lockStatus = AREA_LOCKSTATUS_OK;
    if (AreaTrigger const* at = sObjectMgr.GetMapEntranceTrigger(pCurrChar->GetMapId()))
        lockStatus = pCurrChar->GetAreaTriggerLockStatus(at, miscRequirement);
    else
    {
        // Some basic checks in case of a map without areatrigger
        MapEntry const* mapEntry = sMapStore.LookupEntry(pCurrChar->GetMapId());
        if (!mapEntry)
            lockStatus = AREA_LOCKSTATUS_UNKNOWN_ERROR;
    }
    if (lockStatus != AREA_LOCKSTATUS_OK || !pCurrChar->GetMap()->Add(pCurrChar))
    {
        // normal delayed teleport protection not applied (and this correct) for this case (Player object just created)
        AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId());
        if (at)
            lockStatus = pCurrChar->GetAreaTriggerLockStatus(at, miscRequirement);
        if (!at || lockStatus != AREA_LOCKSTATUS_OK || !pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()))
            pCurrChar->TeleportToHomebind();
    }

    sObjectAccessor.AddObject(pCurrChar);
    // DEBUG_LOG("Player %s added to Map.",pCurrChar->GetName());
    pCurrChar->GetSocial()->SendFriendList();
    pCurrChar->GetSocial()->SendIgnoreList();

    pCurrChar->SendInitialPacketsAfterAddToMap();

    static SqlStatementID updChars;
    static SqlStatementID updAccount;

    SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 1 WHERE guid = ?");
    stmt.PExecute(pCurrChar->GetGUIDLow());

    stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET active_realm_id = ? WHERE id = ?");
    stmt.PExecute(realmID, GetAccountId());

    pCurrChar->SetInGameTime(WorldTimer::getMSTime());

    // announce group about member online (must be after add to player list to receive announce to self)
    if (Group* group = pCurrChar->GetGroup())
        group->UpdatePlayerOnlineStatus(pCurrChar);

    // friend status
    sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetObjectGuid(), 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, TRIGGERED_OLD_TRIGGERED);   // 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, TRIGGERED_OLD_TRIGGERED);        // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)

        pCurrChar->SetWaterWalk(true);
    }

    pCurrChar->TaxiFlightResume();

    // 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->SetPvPFreeForAll(true);

    if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
        pCurrChar->UpdatePvPContested(true);

    // 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);
        SendNotification(LANG_RESET_TALENTS);               // we can use SMSG_TALENTS_INVOLUNTARILY_RESET here
    }

    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TAXINODES))
    {
        pCurrChar->InitTaxiNodes();
        pCurrChar->RemoveAtLoginFlag(AT_LOGIN_RESET_TAXINODES, true);
        SendNotification("Your taxi nodes have been reset.");
    }

    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
        pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);

    // show time before shutdown if shutdown planned.
    if (sWorld.IsShutdowning())
        sWorld.ShutdownMsg(true, pCurrChar);

    if (sWorld.getConfig(CONFIG_BOOL_ALL_TAXI_PATHS))
        pCurrChar->SetTaxiCheater(true);

    if (pCurrChar->isGameMaster())
        SendNotification(LANG_GM_ON);

    if (!pCurrChar->isGMVisible())
    {
        SendNotification(LANG_INVISIBLE_INVISIBLE);
        SpellEntry const* invisibleAuraInfo = sSpellTemplate.LookupEntry<SpellEntry>(sWorld.getConfig(CONFIG_UINT32_GM_INVISIBLE_AURA));
        if (invisibleAuraInfo && IsSpellAppliesAura(invisibleAuraInfo))
            pCurrChar->CastSpell(pCurrChar, invisibleAuraInfo, TRIGGERED_OLD_TRIGGERED);
    }

    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;
    delete holder;
}
Пример #18
0
void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
{
    DETAIL_LOG("WORLD: CMSG_OPEN_ITEM packet, data length = " SIZEFMTD, recvPacket.size());

    uint8 bagIndex, slot;

    recvPacket >> bagIndex >> slot;

    DETAIL_LOG("bagIndex: %u, slot: %u", bagIndex, slot);

    Player* pUser = _player;

    // ignore for remote control state
    if (!pUser->IsSelfMover())
        return;

    Item* pItem = pUser->GetItemByPos(bagIndex, slot);
    if (!pItem)
    {
        pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, nullptr, nullptr);
        return;
    }

    ItemPrototype const* proto = pItem->GetProto();
    if (!proto)
    {
        pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, nullptr);
        return;
    }

    // locked item
    uint32 lockId = proto->LockID;
    if (lockId && !pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_UNLOCKED))
    {
        LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);

        if (!lockInfo)
        {
            pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, nullptr);
            sLog.outError("WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow() , lockId);
            return;
        }

        // required picklocking
        if (lockInfo->Skill[1] || lockInfo->Skill[0])
        {
            pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, nullptr);
            return;
        }
    }

    if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))// wrapped?
    {
        QueryResult* result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow());
        if (result)
        {
            Field* fields = result->Fetch();
            uint32 entry = fields[0].GetUInt32();
            uint32 flags = fields[1].GetUInt32();

            pItem->SetGuidValue(ITEM_FIELD_GIFTCREATOR, ObjectGuid());
            pItem->SetEntry(entry);
            pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags);
            pItem->SetState(ITEM_CHANGED, pUser);
            delete result;
        }
        else
        {
            sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow());
            pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
            return;
        }

        static SqlStatementID delGifts ;

        SqlStatement stmt = CharacterDatabase.CreateStatement(delGifts, "DELETE FROM character_gifts WHERE item_guid = ?");
        stmt.PExecute(pItem->GetGUIDLow());
    }
    else
    {
        Loot*& loot = pItem->loot;
        if (!loot)
            loot = new Loot(pUser, pItem, LOOT_PICKPOCKETING);

        loot->ShowContentTo(pUser);
    }
}
Пример #19
0
void SqlConnection::executeSql(const std::string& sql)
{
  SqlStatement *s = prepareStatement(sql);
  s->execute();
  delete s;
}
Пример #20
0
bool PlayerLogger::SaveToDB(PlayerLogMask mask, bool removeSaved, bool insideTransaction)
{
    bool written = false;
    uint64 serverStart = uint64(sWorld.GetStartTime());
    for (uint8 i = 0; i < MAX_PLAYER_LOG_ENTITIES; ++i)
    {
        if ((mask & CalcLogMask(PlayerLogEntity(i))) == 0 || data[i] == NULL)
            continue;

        if (!insideTransaction)
            CharacterDatabase.BeginTransaction();
        written = true;
        for (uint8 id = 0; id < data[i]->size(); ++id)
        {
            switch (PlayerLogEntity(i))
            {
            case PLAYER_LOG_DAMAGE_GET:
                {
                PlayerLogDamage info = *(PlayerLogDamage*)(&data[i]->at(id));
                static SqlStatementID dmgGetStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(dmgGetStmt, "INSERT INTO playerlog_damage_get SET guid = ?, `time` = ?, aggressor = ?, isPlayer = ?, damage = ?, spell = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addUInt32(info.GetId());
                stmt.addBool(info.IsPlayer());
                stmt.addInt32(info.damage);
                stmt.addUInt16(info.spell);
                stmt.Execute();
                }
                break;
            case PLAYER_LOG_DAMAGE_DONE:
                {
                PlayerLogDamage info = *(PlayerLogDamage*)(&data[i]->at(id));
                static SqlStatementID dmgDoneStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(dmgDoneStmt, "INSERT INTO playerlog_damage_done SET guid = ?, `time` = ?, victim = ?, isPlayer = ?, damage = ?, spell = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addUInt32(info.GetId());
                stmt.addBool(info.IsPlayer());
                stmt.addInt32(info.damage);
                stmt.addUInt16(info.spell);
                stmt.Execute();
                }
                break;
            case PLAYER_LOG_LOOTING:
                {
                PlayerLogLooting info = *(PlayerLogLooting*)(&data[i]->at(id));
                static SqlStatementID lootStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(lootStmt, "INSERT INTO playerlog_looting SET guid = ?, `time`= ?, item = ?, sourceType = ?, sourceEntry = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addUInt32(info.GetItemEntry());
                stmt.addUInt8(uint8(info.GetLootSourceType()));
                stmt.addUInt32(info.droppedBy);
                stmt.Execute();
                }
                break;
            case PLAYER_LOG_TRADE:
                {
                PlayerLogTrading info = *(PlayerLogTrading*)(&data[i]->at(id));
                static SqlStatementID tradeStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(tradeStmt, "INSERT INTO playerlog_trading SET guid = ?, `time`= ?, itemEntry = ?, itemGuid = ?, aquired = ?, partner = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addUInt32(info.GetItemEntry());
                stmt.addUInt32(info.itemGuid);
                stmt.addBool(info.IsItemAquired());
                stmt.addUInt16(info.partner);
                stmt.Execute();
                }
                break;
            case PLAYER_LOG_KILL:
                {
                PlayerLogKilling info = *(PlayerLogKilling*)(&data[i]->at(id));
                static SqlStatementID killStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(killStmt, "INSERT INTO playerlog_killing SET guid = ?, `time`= ?, iskill = ?, entry = ?, victimGuid = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addBool(info.IsKill());
                stmt.addUInt32(info.GetUnitEntry());
                stmt.addUInt32(info.unitGuid);
                stmt.Execute();
                }
                break;
            case PLAYER_LOG_POSITION:
                {
                PlayerLogPosition info = *(PlayerLogPosition*)(&data[i]->at(id));
                static SqlStatementID posStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(posStmt, "INSERT INTO playerlog_position SET guid = ?, `time`= ?, map = ?, posx = ?, posy = ?, posz = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addUInt16(info.map);
                stmt.addFloat(info.x);
                stmt.addFloat(info.y);
                stmt.addFloat(info.z);
                stmt.Execute();
                }
                break;
            case PLAYER_LOG_PROGRESS:
                {
                PlayerLogProgress info = *(PlayerLogProgress*)(&data[i]->at(id));
                static SqlStatementID progStmt;
                SqlStatement stmt = CharacterDatabase.CreateStatement(progStmt, "INSERT INTO playerlog_progress SET guid = ?, `time` = ?, type = ?, level = ?, data = ?, map = ?, posx = ?, posy = ?, posz = ?");
                stmt.addUInt32(playerGuid);
                stmt.addUInt64(info.timestamp + serverStart);
                stmt.addUInt8(info.progressType);
                stmt.addUInt8(info.level);
                stmt.addUInt16(info.data);
                stmt.addUInt16(info.map);
                stmt.addFloat(info.x);
                stmt.addFloat(info.y);
                stmt.addFloat(info.z);
                stmt.Execute();
                }
            }
        }
        Stop(PlayerLogEntity(i));
        if (removeSaved)
            data[i]->clear();
    }
    if (written && !insideTransaction)
        CharacterDatabase.CommitTransaction();

    return written;
}
Пример #21
0
/*----------------------------------------------------------------------------------------------
	Save data in the cache, to the database.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP VwRsOdbcDa::Save(SqlDb & sdb)
{
	BEGIN_COM_METHOD

	const kcchErrMsgBuf = 1024;
	const kcbFmtBufMax = 1024;
	const kcchMaxColNameSize = 200;

	SQLINTEGER cbColVal;
	SDWORD cbClassName;
	long cbHvo;
	SDWORD cbFieldName;
	SDWORD cbFlid;
	int cbFmtBufSize = kcbFmtBufMax;
	int cbFmtSpaceTaken;
	SDWORD cbType;
	SQLUSMALLINT cParamsProcessed = 0;
	HRESULT hr;
	FieldMetaDataMap fmdm;		//  REVIEW PaulP:  Would be nice to have this kept globally.
	FieldMetaDataRec fmdr;
	int nColVal;
	int nFlid;
	ITsStringPtr qtssColVal;
	RETCODE rc;
	byte * rgbFmt = NewObj byte[kcbFmtBufMax]; //[kcbFmtBufMax];
	SmartBstr sbstr;
	SQLCHAR sqlchSqlState[5];
	SQLCHAR sqlchMsgTxt[kcchErrMsgBuf];
	SQLINTEGER sqlnNativeErrPtr;
	SQLSMALLINT sqlnTextLength;
	SQLRETURN sqlr;
	SqlStatement sstmt;
	StrUni suColumnName;
	StrUni suFieldMetaDataSql;
	StrUni suSql;
	StrUni suTableName;
	wchar wchClassName[kcchMaxColNameSize];
	wchar wchFieldName[kcchMaxColNameSize];


	Assert(sdb.IsOpen());


	/*------------------------------------------------------------------------------------------
		If a pointer to a HashMap of field$ metadata information was not passed in as a
		parameter, create the HashMap.  The metaData includes all field names, field types,
		class names, and destination class name from the field$ and class$ tables.
		This information is needed since only store the "flid" value is stored in the cache
		(as the "tag") so when it comes time to do SQL "insert" and "update" statements,
		one need's to know what table and column needs to be affected.

		REVIEW PaulP:  Should really cache this information globally so that it does not have
		to be reloaded each time the view cache is saved.  The only time this info would have
		to be reloaded is when custom fields are added.  Perhaps we could have a table with
		a single record which indicates the last date/time a change to the database was made.
		This could be compared with the currently loaded date each time the cache is saved to
		see if there is a need to reload the field$ meta information.  Of course, if we
		require that only one user is allowed to be connected for a custom field addition,
		this would not be necessary.

		TOxDO PaulP:  Cleanup on any error exit, including db rollback.
						CheckSqlRc(SQLEndTran(SQL_HANDLE_DBC, sdb.Hdbc(), SQL_ROLLBACK));
	------------------------------------------------------------------------------------------*/
	try
	{
		//  Set up SQL statment to obtain meta data.
		suFieldMetaDataSql.Format(
			L"select f.Id FLID, Type, f.Name FLD_NAME,"
			L" c.Name CLS_NAME"
			L" from Field$ f"
			L" join Class$ c on c.id = f.Class"
			L" order by f.id");
		sstmt.Init(sdb);
		CheckSqlRc(SQLExecDirectW(sstmt.Hstmt(), \
			const_cast<wchar *>(suFieldMetaDataSql.Chars()), SQL_NTS));

		//  Bind Columns.
		rc = SQLSetStmtAttr(sstmt.Hstmt(), SQL_ATTR_PARAMS_PROCESSED_PTR, &cParamsProcessed, 0);
		CheckSqlRc(SQLBindCol(sstmt.Hstmt(), 1, SQL_C_SLONG, &nFlid, isizeof(int),
			&cbFlid));
		CheckSqlRc(SQLBindCol(sstmt.Hstmt(), 2, SQL_C_SLONG, &fmdr.m_iType,
			isizeof(fmdr.m_iType), &cbType));
		CheckSqlRc(SQLBindCol(sstmt.Hstmt(), 3, SQL_C_WCHAR, &wchFieldName,
			kcchMaxColNameSize, &cbFieldName));
		CheckSqlRc(SQLBindCol(sstmt.Hstmt(), 4, SQL_C_WCHAR, &wchClassName,
			kcchMaxColNameSize, &cbClassName));

		//  Put info from the columns into a FieldMetaDataRec record and insert
		//  this in the FieldMetaData HashMap.
		for (;;)
		{
			rc = SQLFetch(sstmt.Hstmt());
			if (rc != SQL_SUCCESS)
				break;
			// TOxDO PaulP:  Change this so it just gets a null terminated string!!!
			fmdr.m_suFieldName.Assign(wchFieldName, kcchMaxColNameSize);
			fmdr.m_suClassName.Assign(wchClassName, kcchMaxColNameSize);
			fmdm.Insert(nFlid, fmdr);
		}
		if (rc != SQL_NO_DATA)
		{
			//  REVIEW PaulP (SteveMc): Handle possible error message?
			ThrowHr(WarnHr(E_UNEXPECTED));
		}
		sstmt.Clear();
	}
	catch (...)
	{
		sstmt.Clear();
		delete rgbFmt;
		return E_UNEXPECTED;
	}


	/*------------------------------------------------------------------------------------------
		For every key in the "m_soprMods" ObjPropSet set (ie. all the object properties
		that have been updated), look up that key in the appropriate HashMap and form an SQL
		"update" statement according to the field$ "Type".

		This begins a single database transaction.  All the data in the application view cache
		must either be inserted/updated to the database successfully or the action should fail.
		This necessitates that the database connection is in manual-commit mode.

		REVIEW PaulP:  It is probably faster to collect all the properties for a given object
		type and update the table in the database all with one SQL statement but this will
		do for now until the OLE DB stuff is done.
	------------------------------------------------------------------------------------------*/
	try
	{
		ObjPropSet::iterator itops;
		for (itops = m_soprMods.Begin(); itops != m_soprMods.End(); ++itops)
		{
			//  Get the oprKey from the "update object property" Set.
			ObjPropRec & oprKey = itops.GetValue();

			//  Get the field$ metadata information based on the tag of that oprKey.
			fmdm.Retrieve(oprKey.m_tag, &fmdr);

			//  Initialize and form the SQL statment based on the field "type".
			sstmt.Init(sdb);
			switch (fmdr.m_iType)
			{
				case kcptNil:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;

				case kcptBoolean:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;

				case kcptInteger:
					//  Prepare the SQL statement.  (Uses parameters).
					suSql.Format(L"update %s set %s=? where id=?", fmdr.m_suClassName.Chars(),
						fmdr.m_suFieldName.Chars());
					rc = SQLPrepareW(sstmt.Hstmt(), const_cast<wchar *>(suSql.Chars()),
						SQL_NTS);

					//  Get the integer value from the appropriate HashMap.
					if (m_hmoprn.Retrieve(oprKey, &nColVal))
					{
						//  Bind integer value as the first parameter.
						if (nColVal)
						{
							rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
								SQL_C_SLONG, SQL_INTEGER, 0, 0, &nColVal, 0, &cbColVal);
						}
						else
						{
							// REVIEW JohnT:  How do we indicate in the HashMap that the user
							//		wants to set an integer to NULL?
							cbColVal = SQL_NULL_DATA;
							rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
								SQL_C_SLONG, SQL_INTEGER, 0, 0, NULL, 0, &cbColVal);
						}

						//  Bind the HVO (Id) as the second parameter.
						rc = SQLBindParameter(sstmt.Hstmt(), 2, SQL_PARAM_INPUT,
							SQL_C_SLONG, SQL_INTEGER, 0, 0, &(oprKey.m_hvo), 0, &cbHvo);
					}
					else
					{
						ThrowHr(WarnHr(E_UNEXPECTED));
					}
					break;


				case kcptNumeric:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptFloat:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptTime:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptGuid:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptImage:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptGenDate:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptBinary:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;


				case kcptString:
				case kcptBigString:

					//  Prepare the SQL statement.  (Uses parameters.)
					//  REVIEW PaulP:  Should I be hard-coding "_Fmt" in like this?
					suSql.Format(L"update %s set %s=?, %s_Fmt=? where id=?",
						fmdr.m_suClassName.Chars(), fmdr.m_suFieldName.Chars(),
						fmdr.m_suFieldName.Chars());
					rc = SQLPrepareW(sstmt.Hstmt(), const_cast<wchar *>(suSql.Chars()),
						SQL_NTS);

					if (m_hmoprtss.Retrieve(oprKey, qtssColVal))
					{
						//  Obtain a SmartBstr from the COM smart pointer that points
						//  to the TsString.
						CheckHr(qtssColVal->get_Text(&sbstr));
						if (sbstr.Length())
						{
							//  Copy format information of the TsString to byte array rgbFmt.
							hr = qtssColVal->SerializeFmtRgb(rgbFmt, cbFmtBufSize,
								&cbFmtSpaceTaken);
							if (hr != S_OK)
							{
								if (hr == S_FALSE)
								{
									//  If the supplied buffer is too small, try it again with
									//  the value that cbFmtSpaceTaken was set to.  If this
									//   fails, throw error.
									delete rgbFmt;
									rgbFmt = NewObj byte[cbFmtSpaceTaken];
									cbFmtBufSize = cbFmtSpaceTaken;
									CheckHr(qtssColVal->SerializeFmtRgb(rgbFmt, cbFmtBufSize,
										&cbFmtSpaceTaken));
								}
								else
								{
									ThrowHr(WarnHr(E_UNEXPECTED));
								}
							}

							//  Bind the text and format parts of the string to the parameters.
							SQLINTEGER cbTextPart = sbstr.Length() * 2;
							rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
								SQL_C_WCHAR, SQL_WVARCHAR, cbTextPart, 0,
								const_cast<wchar *>(sbstr.Chars()), cbTextPart, &cbTextPart);
							SQLINTEGER cbFmtPart = cbFmtSpaceTaken;
							rc = SQLBindParameter(sstmt.Hstmt(), 2, SQL_PARAM_INPUT,
								SQL_C_BINARY, SQL_VARBINARY, cbFmtPart, 0, rgbFmt, cbFmtPart,
								&cbFmtPart);
						}
						else
						{
							//  Since the string had no length, bind NULL to the parameters.
							SQLINTEGER cbTextPart = SQL_NULL_DATA;
							rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
								SQL_C_WCHAR, SQL_WVARCHAR, 1, 0, NULL, 0, &cbTextPart);
							//  REVIEW PaulP:  Should we set the Fmt info to NULL for NULL
							//     strings or should we use the Fmt info returned from the
							//     TsString?
							SQLINTEGER cbFmtPart = SQL_NULL_DATA;
							rc = SQLBindParameter(sstmt.Hstmt(), 2, SQL_PARAM_INPUT,
								SQL_C_BINARY, SQL_VARBINARY, 1, 0, NULL, 0, &cbFmtPart);
						}
					}
					else
					{
						ThrowHr(WarnHr(E_UNEXPECTED));
					}

					//  Bind the HVO (ie. Id) value.
					rc = SQLBindParameter(sstmt.Hstmt(), 3, SQL_PARAM_INPUT, SQL_C_SLONG,
						SQL_INTEGER, 0, 0, &(oprKey.m_hvo), 0, &cbHvo);
					break;


				case kcptBigUnicode:
				case kcptUnicode:

					//  Prepare the SQL statement.  (Uses parameters.)
					suSql.Format(L"update %s set %s=? where id=?", fmdr.m_suClassName.Chars(),
						fmdr.m_suFieldName.Chars());
					rc = SQLPrepareW(sstmt.Hstmt(), const_cast<wchar *>(suSql.Chars()),
						SQL_NTS);

					if (m_hmoprtss.Retrieve(oprKey, qtssColVal))
					{
						//  Obtain a SmartBstr from the COM smart pointer that
						//  points to a TsString.
						CheckHr(qtssColVal->get_Text(&sbstr));
						if (sbstr.Length())
						{
							//  Bind the string parameter.
							SQLINTEGER cbTextPart = sbstr.Length() * 2;
							rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
								SQL_C_WCHAR, SQL_WVARCHAR, cbTextPart, 0,
								const_cast<wchar *>(sbstr.Chars()), cbTextPart, &cbTextPart);
						}
						else
						{
							//  If the string had no length, bind NULL to the parameter.
							SQLINTEGER cbTextPart = SQL_NULL_DATA;
							rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
								SQL_C_WCHAR, SQL_WVARCHAR, 1, 0, NULL, 0, &cbTextPart);
						}
					}
					else
					{
						ThrowHr(WarnHr(E_UNEXPECTED));
					}

					//  Bind the HVO (ie. Id) value.
					rc = SQLBindParameter(sstmt.Hstmt(), 2, SQL_PARAM_INPUT, SQL_C_SLONG,
						SQL_INTEGER, 0, 0, &(oprKey.m_hvo), 0, &cbHvo);
					break;

				case kcptOwningAtom:
					//  Update owning field.
					//  Update Owner$ object of CmObject.
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptReferenceAtom:
					//  This is basically the same as the Integer case except we obtain the
					//  value from the m_hmoprobj HashMap rather than the m_hmoprn HashMap.
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptOwningCollection:
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptReferenceCollection:
					//  Affect the joiner table.
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptOwningSequence:
					//  Need to update.
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				case kcptReferenceSequence:
					//  Affect the joiner table.
					ThrowHr(WarnHr(E_NOTIMPL));
					break;
				default:
					ThrowHr(WarnHr(E_UNEXPECTED));
					break;
			}

			//  Execute the SQL update command.
			//rc = SQLSetStmtAttr(sstmt.Hstmt(), SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
			rc = SQLExecute(sstmt.Hstmt());
			if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO)
			{
				//  TOxDO PaulP:  Error information can be obtained from sqlchMsgTxt.
				sqlr = SQLGetDiagRec(SQL_HANDLE_STMT, sstmt.Hstmt(), 1, sqlchSqlState,
					&sqlnNativeErrPtr, sqlchMsgTxt, kcchErrMsgBuf, &sqlnTextLength);
				ThrowHr(WarnHr(E_UNEXPECTED));
			}
			sstmt.Clear();
		}


		/*--------------------------------------------------------------------------------------
			Go through the m_soperMods ObjPropSet set and update columns in the MultiX tables.
		--------------------------------------------------------------------------------------*/
		ObjPropEncSet::iterator itopes;
		for (itopes = m_soperMods.Begin(); itopes != m_soperMods.End(); ++itopes)
		{
			//  Get the operKey from the "update MSA" Set.
			ObjPropEncRec & operKey = itopes.GetValue();

			//  Get the field$ metadata information based on the tag of that operKey.
			fmdm.Retrieve(operKey.m_tag, &fmdr);

			//  Initialize and form the SQL statment.
			sstmt.Init(sdb);
			if (m_hmopertss.Retrieve(operKey, qtssColVal))
			{
				//  Obtain a SmartBstr from the COM smart pointer that points to the TsString.
				CheckHr(qtssColVal->get_Text(&sbstr));
				if (sbstr.Length())
				{
					//  Get the format of the TsString
					hr = qtssColVal->SerializeFmtRgb(rgbFmt, cbFmtBufSize, &cbFmtSpaceTaken);
					if (hr != S_OK)
					{
						if (hr == S_FALSE)
						{
							//  If the supplied buffer is too small, try it again with the value
							//  that cbFmtSpaceTaken was set to.  If this fails, signal error.
							delete rgbFmt;
							rgbFmt = NewObj byte[cbFmtSpaceTaken];
							cbFmtBufSize = cbFmtSpaceTaken;
							CheckHr(qtssColVal->SerializeFmtRgb(rgbFmt, cbFmtBufSize,
								&cbFmtSpaceTaken));
						}
						else
						{
							ThrowHr(WarnHr(E_UNEXPECTED));
						}
					}

					//  Execute stored procedure to set MSA value.
					//  REVIEW PaulP:  This technique isn't going to work for custom fields
					//		since there will likely not be any "Set" stored procedure.
					suSql.Format(L"exec Set_%s_%s %d, %d, ?, ?", fmdr.m_suClassName.Chars(),
						fmdr.m_suFieldName.Chars(), operKey.m_hvo, operKey.m_ws);
					rc = SQLPrepareW(sstmt.Hstmt(), const_cast<wchar *>(suSql.Chars()),
						SQL_NTS);

					//  Bind the text and format parts of the string to the parameters.
					SQLINTEGER cbTextPart = sbstr.Length() * 2;
					rc = SQLBindParameter(sstmt.Hstmt(), 1, SQL_PARAM_INPUT,
						SQL_C_WCHAR, SQL_WVARCHAR, cbTextPart, 0,
						const_cast<wchar *>(sbstr.Chars()), cbTextPart, &cbTextPart);

					SQLINTEGER cbFmtPart = cbFmtSpaceTaken;
					rc = SQLBindParameter(sstmt.Hstmt(), 2, SQL_PARAM_INPUT, SQL_C_BINARY,
					SQL_VARBINARY, cbFmtPart, 0, rgbFmt, cbFmtPart, &cbFmtPart);
				}
				else
				{
					//  REVIEW PaulP:  This technique isn't going to work for custom fields
					//		since there will likely not be any "Set" stored procedure.
					suSql.Format(L"exec Set_%s_%s %d, %d, NULL, NULL",
						fmdr.m_suClassName.Chars(), fmdr.m_suFieldName.Chars(), operKey.m_hvo,
						operKey.m_ws);
					rc = SQLPrepareW(sstmt.Hstmt(), const_cast<wchar *>(suSql.Chars()),
						SQL_NTS);
				}

				//  Execute the SQL update command.
				//rc = SQLSetStmtAttr(sstmt.Hstmt(), SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
				rc = SQLExecute(sstmt.Hstmt());
				if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO)
				{
					//  TOxDO PaulP:  Error information can be obtained from sqlchMsgTxt.
					sqlr = SQLGetDiagRec(SQL_HANDLE_STMT, sstmt.Hstmt(), 1, sqlchSqlState,
						&sqlnNativeErrPtr, sqlchMsgTxt, kcchErrMsgBuf, &sqlnTextLength);
					ThrowHr(WarnHr(E_UNEXPECTED));
				}
				sstmt.Clear();
			}
			else
			{
				ThrowHr(WarnHr(E_UNEXPECTED));
			}
		}


		/*--------------------------------------------------------------------------------------
			Commit the database transaction.
			REVIEW PaulP:  The DataSource MUST be in manual commit mode.
		--------------------------------------------------------------------------------------*/
		CheckSqlRc(SQLEndTran(SQL_HANDLE_DBC, sdb.Hdbc(), SQL_COMMIT));

	}
	catch (...)
	{
		sstmt.Clear();
		delete rgbFmt;
		CheckSqlRc(SQLEndTran(SQL_HANDLE_DBC, sdb.Hdbc(), SQL_ROLLBACK));
		return E_UNEXPECTED;
	}


	/*------------------------------------------------------------------------------------------
		Clear the two Sets containing records of modified properties and MBA's.
	------------------------------------------------------------------------------------------*/
	m_soprMods.Clear();
	m_soperMods.Clear();
	delete rgbFmt; // REVIEW: Shouldn't this be delete[]?

	return S_OK;

	END_COM_METHOD(g_fact, IID_IVwCacheDa);
}
Пример #22
0
void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder)
{
    // The following fixes a crash. Use case:
    // Session1 created, requests login, kicked.
    // Session2 created, requests login, and receives 2 login callback.
    if (GetPlayer() || !m_playerLoading)
    {
        sLog.outInfo("[CRASH] HandlePlayerLogin on session %u with player %s [loading=%u]", GetAccountId(), GetPlayerName(), m_playerLoading);
        delete holder;
        m_playerLoading = false;
        return;
    }
    ObjectGuid playerGuid = holder->GetGuid();
    ASSERT(playerGuid.IsPlayer());

    // If the character is online (ALT-F4 logout for example)
    Player *pCurrChar = sObjectAccessor.FindPlayer(playerGuid);
    MasterPlayer* pCurrMasterPlayer = sObjectAccessor.FindMasterPlayer(playerGuid);
    bool alreadyOnline = false;
    if (pCurrChar)
    {
        // Hacking attempt
        if (pCurrChar->GetSession()->GetAccountId() != GetAccountId())
        {
            KickPlayer();
            delete holder;
            m_playerLoading = false;
            return;
        }
        pCurrChar->GetSession()->SetPlayer(NULL);
        pCurrChar->SetSession(this);
        // Need to attach packet bcaster to the new socket
        pCurrChar->m_broadcaster->ChangeSocket(GetSocket());
        alreadyOnline = true;
        // If the character had a logout request, then he is articifially stunned (cf CMSG_LOGOUT_REQUEST handler). Fix it here.
        if (pCurrChar->CanFreeMove())
        {
            pCurrChar->SetMovement(MOVE_UNROOT);
            pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
            pCurrChar->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
        }
    }
    else
    {
        // Character found online but not in world ?
        if (HashMapHolder<Player>::Find(playerGuid))
        {
            sLog.outInfo("[CRASH] Trying to login already ingame character guid %u", playerGuid.GetCounter());
            KickPlayer();
            delete holder;
            m_playerLoading = false;
            return;
        }
        pCurrChar = new Player(this);
        pCurrChar->GetMotionMaster()->Initialize();
    }

    // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools)
    if (alreadyOnline)
        pCurrChar->SendPacketsAtRelogin();
    else if (!pCurrChar->LoadFromDB(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;
    }

    ASSERT(pCurrChar->GetSession() == this);
    SetPlayer(pCurrChar);
    if (pCurrMasterPlayer)
    {
        pCurrMasterPlayer->GetSession()->SetMasterPlayer(NULL);
        pCurrMasterPlayer->SetSession(this);
        m_masterPlayer = pCurrMasterPlayer;
    }
    else
    {
        m_masterPlayer = new MasterPlayer(this);
        m_masterPlayer->LoadPlayer(GetPlayer());
        m_masterPlayer->LoadActions(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACTIONS));
        m_masterPlayer->LoadSocial(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST));
        m_masterPlayer->LoadMails(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILS));
        m_masterPlayer->LoadMailedItems(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILEDITEMS));
    }
    m_masterPlayer->UpdateNextMailTimeAndUnreads();

    sObjectAccessor.AddObject(m_masterPlayer);

    WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20);
    data << pCurrChar->GetMapId();
    data << pCurrChar->GetPositionX();
    data << pCurrChar->GetPositionY();
    data << pCurrChar->GetPositionZ();
    data << pCurrChar->GetOrientation();
    SendPacket(&data);

    data.Initialize(SMSG_ACCOUNT_DATA_TIMES, 128);
    for (int i = 0; i < 32; ++i)
        data << uint32(0);
    SendPacket(&data);

    // Send MOTD (1.12.1 not have SMSG_MOTD, so do it in another way)
    {
        uint32 linecount = 0;
        std::string str_motd = sWorld.GetMotd();
        std::string::size_type pos, nextpos;
        std::string motd;

        pos = 0;
        while ((nextpos = str_motd.find('@', pos)) != std::string::npos)
        {
            if (nextpos != pos)
            {
                ChatHandler(pCurrChar).PSendSysMessage(str_motd.substr(pos, nextpos - pos).c_str());
                ++linecount;
            }
            pos = nextpos + 1;
        }

        if (pos < str_motd.length())
        {
            ChatHandler(pCurrChar).PSendSysMessage(str_motd.substr(pos).c_str());
            ++linecount;
        }

        DEBUG_LOG("WORLD: Sent motd (SMSG_MOTD)");
    }

    if (!alreadyOnline)
    {
        //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow());
        QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD);

        if (resultGuild)
        {
            Field *fields = resultGuild->Fetch();
            pCurrChar->SetInGuild(fields[0].GetUInt32());
            pCurrChar->SetRank(fields[1].GetUInt32());
        }
        else if (pCurrChar->GetGuildId())                       // clear guild related fields in case wrong data about nonexistent membership
        {
            pCurrChar->SetInGuild(0);
            pCurrChar->SetRank(0);
        }

        if (pCurrChar->GetGuildId() != 0)
        {
            Guild* guild = sGuildMgr.GetGuildById(pCurrChar->GetGuildId());
            if (guild)
            {
                data.Initialize(SMSG_GUILD_EVENT, (2 + guild->GetMOTD().size() + 1));
                data << uint8(GE_MOTD);
                data << uint8(1);
                data << guild->GetMOTD();
                SendPacket(&data);
                DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)");

                guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetObjectGuid(), pCurrChar->GetName());
            }
            else
            {
                // remove wrong guild data
                sLog.outError("Player %s (GUID: %u) marked as member of nonexistent guild (id: %u), removing guild membership for player.", pCurrChar->GetName(), pCurrChar->GetGUIDLow(), pCurrChar->GetGuildId());
                pCurrChar->SetInGuild(0);
            }
        }
    }

    if (!pCurrChar->isAlive())
        pCurrChar->SendCorpseReclaimDelay(true);

    pCurrChar->SendInitialPacketsBeforeAddToMap();
    GetMasterPlayer()->SendInitialActionButtons();

    //Show cinematic at the first time that player login
    if (!pCurrChar->getCinematic())
    {
        pCurrChar->setCinematic(1);

        if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()))
            pCurrChar->SendCinematicStart(rEntry->CinematicSequence);
    }

    if (!alreadyOnline && !pCurrChar->GetMap()->Add(pCurrChar))
    {
        // normal delayed teleport protection not applied (and this correct) for this case (Player object just created)
        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->TeleportToHomebind();
    }

    if (alreadyOnline)
        pCurrChar->GetMap()->ExistingPlayerLogin(pCurrChar); // SendInitSelf ...
    else
        sObjectAccessor.AddObject(pCurrChar);

    //DEBUG_LOG("Player %s added to Map.",pCurrChar->GetName());
    pCurrChar->GetSocial()->SendFriendList();
    pCurrChar->GetSocial()->SendIgnoreList();

    pCurrChar->SendInitialPacketsAfterAddToMap();
    if (alreadyOnline)
        pCurrChar->SendInitWorldStates(pCurrChar->GetCachedZoneId());

    static SqlStatementID updChars;
    static SqlStatementID updAccount;

    SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 1 WHERE guid = ?");
    stmt.PExecute(pCurrChar->GetGUIDLow());

    stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET current_realm = ?, online = 1 WHERE id = ?");
    stmt.PExecute(realmID, GetAccountId());

    pCurrChar->SetInGameTime(WorldTimer::getMSTime());

    // announce group about member online (must be after add to player list to receive announce to self)
    if (Group *group = pCurrChar->GetGroup())
        group->UpdatePlayerOnlineStatus(pCurrChar);

    // friend status
    // TODO: Call it when node finished loading also
    if (GetMasterPlayer())
        sSocialMgr.SendFriendStatus(GetMasterPlayer(), FRIEND_ONLINE, GetMasterPlayer()->GetObjectGuid(), true);

    if (!alreadyOnline)
    {
        // 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);   // 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);        // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)

            pCurrChar->SetMovement(MOVE_WATER_WALK);
        }
    }

    // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned)
    if (alreadyOnline)
        pCurrChar->PetSpellInitialize();
    else
    {
        pCurrChar->ContinueTaxiFlight();
        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->SetFFAPvP(true);

    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);
        SendNotification(LANG_RESET_TALENTS);               // we can use SMSG_TALENTS_INVOLUNTARILY_RESET here
    }

    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
        pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);

    // show time before shutdown if shutdown planned.
    if (sWorld.IsShutdowning())
        sWorld.ShutdownMsg(true, pCurrChar);

    if (sWorld.getConfig(CONFIG_BOOL_ALL_TAXI_PATHS))
        pCurrChar->SetTaxiCheater(true);

    if (pCurrChar->isGameMaster())
        SendNotification(LANG_GM_ON);

    if (!pCurrChar->isGMVisible())
        SendNotification(LANG_INVISIBLE_INVISIBLE, pCurrChar->GetGMInvisibilityLevel());

    std::string IP_str = GetRemoteAddress();

    sLog.out(LOG_CHAR, "Account: %d (IP: %s) Login Character:[%s] (guid: %u)%s",
             GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow(), alreadyOnline ? " Player was already online" : "");
    sWorld.LogCharacter(pCurrChar, "Login");
    if (!alreadyOnline && !pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED))
        pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);

    m_playerLoading = false;
    _clientMoverGuid = pCurrChar->GetObjectGuid();
    delete holder;
    if (alreadyOnline)
    {
        pCurrChar->UpdateControl();
        // Send "Release spirit" timer, etc ...
        if (pCurrChar->getDeathState() == CORPSE)
            pCurrChar->KillPlayer();
    }

    // Update warden speeds
    //if (GetWarden())
        //for (int i = 0; i < MAX_MOVE_TYPE; ++i)
            //GetWarden()->SendSpeedChange(UnitMoveType(i), pCurrChar->GetSpeed(UnitMoveType(i)));

    ALL_SESSION_SCRIPTS(this, OnLogin(pCurrChar));
}
Пример #23
0
void Item::DeleteRefundDataFromDB()
{
    static SqlStatementID delRefund;
    SqlStatement stmt = CharacterDatabase.CreateStatement(delRefund, "DELETE FROM item_refund_instance WHERE itemGuid = ?");
    stmt.PExecute(GetGUIDLow());
}
Пример #24
0
void Corpse::SaveToDB()
{
    // prevent DB data inconsistence problems and duplicates
    RealmDataDatabase.BeginTransaction();
    DeleteFromDB();

    static SqlStatementID saveCorpse;
    SqlStatement stmt = RealmDataDatabase.CreateStatement(saveCorpse, "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

    stmt.addUInt64(GetGUIDLow());
    stmt.addUInt64(GUID_LOPART(GetOwnerGUID()));
    stmt.addFloat(GetPositionX());
    stmt.addFloat(GetPositionY());
    stmt.addFloat(GetPositionZ());
    stmt.addFloat(GetOrientation());
    stmt.addUInt32(GetZoneId());
    stmt.addUInt32(GetMapId());
    stmt.addString(GetUInt32ValuesString());
    stmt.addUInt64(m_time);
    stmt.addUInt32(GetType());
    stmt.addInt32(GetInstanceId());

    stmt.Execute();
    RealmDataDatabase.CommitTransaction();
}
Пример #25
0
void Item::SaveToDB()
{
    uint32 guid = GetGUIDLow();

    switch(m_state)
    {
        case ITEM_NEW:
        {
            DeleteFromDB(guid);

            std::ostringstream ss;
            for (uint16 i = 0; i < m_valuesCount; ++i)
                ss << GetUInt32Value(i) << " ";

            static SqlStatementID insItem;
            SqlStatement stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid, owner_guid, data, text) VALUES (?, ?, ?, ?)");
            stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str(), m_text.c_str());

            break;
        }
        case ITEM_CHANGED:
        {
            std::ostringstream ss;
            for (uint16 i = 0; i < m_valuesCount; ++i)
                ss << GetUInt32Value(i) << " ";

            static SqlStatementID updInstance;
            SqlStatement stmt = CharacterDatabase.CreateStatement(updInstance, "UPDATE item_instance SET data = ?, owner_guid = ?, text = ? WHERE guid = ?");
            stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), m_text.c_str(), guid);

            if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
            {
                static SqlStatementID updGifts;
                stmt = CharacterDatabase.CreateStatement(updGifts, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?");
                stmt.PExecute(GetOwnerGuid().GetCounter(), GetGUIDLow());
            }

            break;
        }
        case ITEM_REMOVED:
        {
            DeleteFromDB(guid);

            if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
                DeleteGiftsFromDB();

            if (HasSavedLoot())
                DeleteLootFromDB();

            if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
                DeleteRefundDataFromDB();

            if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_BOP_TRADEABLE))
                DeleteSoulboundTradeableFromDB();

            delete this;
            return;
        }
        case ITEM_UNCHANGED:
            return;
    }

    if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED)
        DeleteLootFromDB();

    if (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED)
    {
        if (Player* owner = GetOwner())
        {
            // save money as 0 itemid data
            if (loot.gold)
            {
                static SqlStatementID saveGold;
                SqlStatement stmt = CharacterDatabase.CreateStatement(saveGold, "INSERT INTO item_loot (guid, owner_guid, itemid, amount, suffix, property) VALUES (?, ?, 0, ?, 0, 0)");
                stmt.PExecute(GetGUIDLow(), owner->GetGUIDLow(), loot.gold);
            }

            static SqlStatementID saveLoot;
            SqlStatement stmt = CharacterDatabase.CreateStatement(saveLoot, "INSERT INTO item_loot (guid, owner_guid, itemid, amount, suffix, property) VALUES (?, ?, ?, ?, ?, ?)");

            // save items and quest items (at load its all will added as normal, but this not important for item loot case)
            for (size_t i = 0; i < loot.GetMaxSlotInLootFor(owner); ++i)
            {
                QuestItem* qitem = NULL;

                LootItem* item = loot.LootItemInSlot(i, owner, &qitem);
                if (!item)
                    continue;

                // questitems use the blocked field for other purposes
                if (!qitem && item->is_blocked)
                    continue;

                stmt.addUInt32(GetGUIDLow());
                stmt.addUInt32(owner->GetGUIDLow());
                stmt.addUInt32(item->itemid);
                stmt.addUInt8(item->count);
                stmt.addUInt32(item->randomSuffix);
                stmt.addInt32(item->randomPropertyId);
                stmt.Execute();
            }
        }
    }

    if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY)
        SetLootState(ITEM_LOOT_UNCHANGED);

    SetState(ITEM_UNCHANGED);
}
Пример #26
0
void Item::SaveToDB()
{
    uint32 guid = GetGUIDLow();
    switch (uState)
    {
        case ITEM_NEW:
        {
            static SqlStatementID delItem ;
            static SqlStatementID insItem ;

            SqlStatement stmt = CharacterDatabase.CreateStatement(delItem, "DELETE FROM item_instance WHERE guid = ?");
            stmt.PExecute(guid);

            std::ostringstream ss;
            for (uint16 i = 0; i < m_valuesCount; ++i)
                ss << GetUInt32Value(i) << " ";

            stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid,owner_guid,data) VALUES (?, ?, ?)");
            stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str());
        } break;
        case ITEM_CHANGED:
        {
            static SqlStatementID updInstance ;
            static SqlStatementID updGifts ;

            SqlStatement stmt = CharacterDatabase.CreateStatement(updInstance, "UPDATE item_instance SET data = ?, owner_guid = ? WHERE guid = ?");

            std::ostringstream ss;
            for (uint16 i = 0; i < m_valuesCount; ++i)
                ss << GetUInt32Value(i) << " ";

            stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), guid);

            if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
            {
                stmt = CharacterDatabase.CreateStatement(updGifts, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?");
                stmt.PExecute(GetOwnerGuid().GetCounter(), GetGUIDLow());
            }
        } break;
        case ITEM_REMOVED:
        {
            static SqlStatementID delItemText;
            static SqlStatementID delInst ;
            static SqlStatementID delGifts ;
            static SqlStatementID delLoot ;

            if (uint32 item_text_id = GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID))
            {
                SqlStatement stmt = CharacterDatabase.CreateStatement(delItemText, "DELETE FROM item_text WHERE id = ?");
                stmt.PExecute(item_text_id);
            }

            SqlStatement stmt = CharacterDatabase.CreateStatement(delInst, "DELETE FROM item_instance WHERE guid = ?");
            stmt.PExecute(guid);

            if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
            {
                stmt = CharacterDatabase.CreateStatement(delGifts, "DELETE FROM character_gifts WHERE item_guid = ?");
                stmt.PExecute(GetGUIDLow());
            }

            if (HasSavedLoot())
            {
                stmt = CharacterDatabase.CreateStatement(delLoot, "DELETE FROM item_loot WHERE guid = ?");
                stmt.PExecute(GetGUIDLow());
            }

            delete this;
            return;
        }
        case ITEM_UNCHANGED:
            return;
    }

    if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED)
    {
        static SqlStatementID delLoot ;

        SqlStatement stmt = CharacterDatabase.CreateStatement(delLoot, "DELETE FROM item_loot WHERE guid = ?");
        stmt.PExecute(GetGUIDLow());
    }

    if (loot && (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED))
    {
        if (Player* owner = GetOwner())
        {
            static SqlStatementID saveGold ;
            static SqlStatementID saveLoot ;

            // save money as 0 itemid data
            if (loot->GetGoldAmount())
            {
                SqlStatement stmt = CharacterDatabase.CreateStatement(saveGold, "INSERT INTO item_loot (guid,owner_guid,itemid,amount,property) VALUES (?, ?, 0, ?, 0)");
                stmt.PExecute(GetGUIDLow(), owner->GetGUIDLow(), loot->GetGoldAmount());
            }

            SqlStatement stmt = CharacterDatabase.CreateStatement(saveLoot, "INSERT INTO item_loot (guid,owner_guid,itemid,amount,property) VALUES (?, ?, ?, ?, ?)");

            // save items and quest items (at load its all will added as normal, but this not important for item loot case)
            LootItemList lootList;
            loot->GetLootItemsListFor(owner, lootList);
            for (LootItemList::const_iterator lootItr = lootList.begin(); lootItr != lootList.end(); ++lootItr)
            {
                LootItem* lootItem = *lootItr;
                stmt.addUInt32(GetGUIDLow());
                stmt.addUInt32(owner->GetGUIDLow());
                stmt.addUInt32(lootItem->itemId);
                stmt.addUInt8(lootItem->count);
                stmt.addInt32(lootItem->randomPropertyId);

                stmt.Execute();
            }
        }
    }

    if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY)
        SetLootState(ITEM_LOOT_UNCHANGED);

    SetState(ITEM_UNCHANGED);
}
Пример #27
0
void Item::DeleteFromDB(uint32 guidLow)
{
    static SqlStatementID delItem;
    SqlStatement stmt = CharacterDatabase.CreateStatement(delItem, "DELETE FROM item_instance WHERE guid = ?");
    stmt.PExecute(guidLow);
}
Пример #28
0
void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
    /* Store the player's GUID for later reference */
    ObjectGuid playerGuid = holder->GetGuid();

    /* Create a new instance of the player object */
    Player* pCurrChar = new Player(this);

    /* Initialize a motion generator */
    pCurrChar->GetMotionMaster()->Initialize();

    /* Account ID is validated in LoadFromDB (prevents cheaters logging in to characters not on their account) */
    if (!pCurrChar->LoadFromDB(playerGuid, holder))         /// Could not load character from database, cancel login
    {
        /* Disconnect the game client */
        KickPlayer();

        /* Remove references to avoid dangling pointers */
        delete pCurrChar;
        delete holder;

        /* Checked in WorldSession::Update */
        m_playerLoading = false;

        return;
    }

    /* Validation check completely, assign player to WorldSession::_player for later use */
    SetPlayer(pCurrChar);

    WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20);
    data << pCurrChar->GetMapId();
    data << pCurrChar->GetPositionX();
    data << pCurrChar->GetPositionY();
    data << pCurrChar->GetPositionZ();
    data << pCurrChar->GetOrientation();
    SendPacket(&data);

    data.Initialize(SMSG_ACCOUNT_DATA_TIMES, 128);
    for (int i = 0; i < 32; ++i)
        { data << uint32(0); }
    SendPacket(&data);

    /* 1.12.1 does not have SMSG_MOTD, so we send a server message */
    /* Used for counting number of newlines in MOTD */
    uint32 linecount = 0;
    /* The MOTD itself */
    std::string str_motd = sWorld.GetMotd();
    /* Used for tracking our position within the MOTD while iterating through it */
    std::string::size_type pos = 0, nextpos;

    /* Find the next occurance of @ in the string
     * This is how newlines are represented */
    while ((nextpos = str_motd.find('@', pos)) != std::string::npos)
    {
        /* If these are not equal, it means a '@' was found
         * These are used to represent newlines in the string
         * It is set by the code above here */
        if (nextpos != pos)
        {
            /* Send the player a system message containing the substring from pos to nextpos - pos */
            ChatHandler(pCurrChar).PSendSysMessage(str_motd.substr(pos, nextpos - pos).c_str());
            ++linecount;
        }

        pos = nextpos + 1;
    }
    /* There are no more newlines in our MOTD, so we send whatever is left */
    if (pos < str_motd.length())
    {
        ChatHandler(pCurrChar).PSendSysMessage(str_motd.substr(pos).c_str());
    }
    DEBUG_LOG("WORLD: Sent motd (SMSG_MOTD)");

    /* Attempt to load guild for player */
    if (QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD))
    {
        /* We're in a guild, so set the player's guild data to represent that */
        Field* fields = resultGuild->Fetch();
        pCurrChar->SetInGuild(fields[0].GetUInt32());
        pCurrChar->SetRank(fields[1].GetUInt32());
        /* Avoid dangling pointers */
        delete resultGuild;
    }
    /* Player thinks they have a guild, but it isn't in the database. Clear that information */
    else if (pCurrChar->GetGuildId())
    {
        pCurrChar->SetInGuild(0);
        pCurrChar->SetRank(0);
    }

    /* Player is in a guild
     * TODO: Can we move this code into the block above? Not sure why it's down here */
    if (pCurrChar->GetGuildId() != 0)
    {
        /* Get guild based on what we set the player's guild to above */
        Guild* guild = sGuildMgr.GetGuildById(pCurrChar->GetGuildId());

        /* More checks to see if they're in a guild? I'm sure this is redundant */
        if (guild)
        {
            /* Build MOTD packet and send it to the player */
            data.Initialize(SMSG_GUILD_EVENT, (1 + 1 + guild->GetMOTD().size() + 1));
            data << uint8(GE_MOTD);
            data << uint8(1);
            data << guild->GetMOTD();
            SendPacket(&data);
            DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)");

            /* Let everyone in the guild know you've just signed in */
            guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetObjectGuid(), pCurrChar->GetName());
        }
        /* If the player is not in a guild */
        else
        {
            sLog.outError("Player %s (GUID: %u) marked as member of nonexistent guild (id: %u), removing guild membership for player.",
                          pCurrChar->GetName(),
                          pCurrChar->GetGUIDLow(),
                          pCurrChar->GetGuildId());

            /* Set guild to 0 (again) */
            pCurrChar->SetInGuild(0);
        }
    }

    /* Don't let the player get stuck logging in with no corpse */
    if (!pCurrChar->IsAlive())
    {
        pCurrChar->SendCorpseReclaimDelay(true);
    }

    /* Sends information required before the player can be added to the map
     * TODO: See if we can send information about game objects here (prevent alt+f4 through object) */
    pCurrChar->SendInitialPacketsBeforeAddToMap();

    /* If it's the player's first login, send a cinematic */
    if (!pCurrChar->getCinematic())
    {
        pCurrChar->setCinematic(1);

        /* Set the start location to the player's racial starting point */
        if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()))
            { pCurrChar->SendCinematicStart(rEntry->CinematicSequence); }
    }

    uint32 miscRequirement = 0;
    AreaLockStatus lockStatus = AREA_LOCKSTATUS_OK;
    if (AreaTrigger const* at = sObjectMgr.GetMapEntranceTrigger(pCurrChar->GetMapId()))
    {
        lockStatus = pCurrChar->GetAreaTriggerLockStatus(at, miscRequirement);
    }
    else
    {
        // Some basic checks in case of a map without areatrigger
        MapEntry const* mapEntry = sMapStore.LookupEntry(pCurrChar->GetMapId());
        if (!mapEntry)
            { lockStatus = AREA_LOCKSTATUS_UNKNOWN_ERROR; }
    }

    /* This code is run if we can not add the player to the map for some reason */
    if (lockStatus != AREA_LOCKSTATUS_OK || !pCurrChar->GetMap()->Add(pCurrChar))
    {
        /* Attempt to find an areatrigger to teleport the player for us */
        AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId());
        if (at)
        {
            lockStatus = pCurrChar->GetAreaTriggerLockStatus(at, miscRequirement);
        }

        /* We couldn't find an areatrigger to teleport, so just move the player back to their home bind */
        if (!at || lockStatus != AREA_LOCKSTATUS_OK || !pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()))
        {
            pCurrChar->TeleportToHomebind();
        }
    }

    sObjectAccessor.AddObject(pCurrChar);
    DEBUG_LOG("Player %s added to map %i", pCurrChar->GetName(), pCurrChar->GetMapId());

    /* send the player's social lists */
    pCurrChar->GetSocial()->SendFriendList();
    pCurrChar->GetSocial()->SendIgnoreList();

    /* Send packets that must be sent only after player is added to the map */
    pCurrChar->SendInitialPacketsAfterAddToMap();

    /* Mark player as online in the database */
    static SqlStatementID updChars;
    static SqlStatementID updAccount;

    SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 1 WHERE guid = ?");
    stmt.PExecute(pCurrChar->GetGUIDLow());

    stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET active_realm_id = ? WHERE id = ?");
    stmt.PExecute(realmID, GetAccountId());

    /* Sync player's in-game time with server time */
    pCurrChar->SetInGameTime(WorldTimer::getMSTime());

    /* Send logon notification to player's group
     * This is sent after player is added to the world so that player receives it too */
    if (Group* group = pCurrChar->GetGroup())
        { group->SendUpdate(); }

    /* Inform player's friends that player has come online */
    sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetObjectGuid(), true);

    /* Load the player's corpse if it exists, or resurrect the player if not */
    pCurrChar->LoadCorpse();

    /* If the player is dead, we need to set them as a ghost and increase movespeed */
    if (pCurrChar->m_deathState != ALIVE)
    {
        /* If player is a night elf, wisp racial should be applied */
        if (pCurrChar->getRace() == RACE_NIGHTELF)
        {
            pCurrChar->CastSpell(pCurrChar, 20584, true);   // 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)
        }

        /* Apply ghost spell to player */
        pCurrChar->CastSpell(pCurrChar, 8326, true);        // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)

        /* Allow player to walk on water */
        pCurrChar->SetWaterWalk(true);
    }

    /* If player is on a taxi, continue their flight */
    pCurrChar->ContinueTaxiFlight();

    /* Load pet if player has one
     * If the player is dead or on a taxi, the pet will be remembered as a temporary summon */
    pCurrChar->LoadPet();

    /* If we're running an FFA PvP realm and the player isn't a GM, mark them as PvP flagged */
    if (sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
    {
        pCurrChar->SetFFAPvP(true);
    }

    if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
    {
        pCurrChar->SetContestedPvP();
    }

    /* Apply onLogon requests (such as talent resets) */
    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS))
    {
        pCurrChar->resetSpells();
        SendNotification(LANG_RESET_SPELLS);
    }

    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS))
    {
        pCurrChar->resetTalents(true);
        SendNotification(LANG_RESET_TALENTS);               // we can use SMSG_TALENTS_INVOLUNTARILY_RESET here
    }

    /* We've done what we need to, remove the flag */
    if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
    {
        pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST);
    }

    /* If the server is shutting down, show shutdown time remaining */
    if (sWorld.IsShutdowning())
    {
        sWorld.ShutdownMsg(true, pCurrChar);
    }

    /* If player should have all taxi paths, give them to the player */
    if (sWorld.getConfig(CONFIG_BOOL_ALL_TAXI_PATHS))
    {
        pCurrChar->SetTaxiCheater(true);
    }

    /* Send GM notifications */
    if (pCurrChar->isGameMaster())
    {
        SendNotification(LANG_GM_ON);
    }

    if (!pCurrChar->isGMVisible())
    {
        SendNotification(LANG_INVISIBLE_INVISIBLE);
        SpellEntry const* invisibleAuraInfo = sSpellStore.LookupEntry(sWorld.getConfig(CONFIG_UINT32_GM_INVISIBLE_AURA));
        if (invisibleAuraInfo && IsSpellAppliesAura(invisibleAuraInfo))
            { pCurrChar->CastSpell(pCurrChar, invisibleAuraInfo, true); }
    }

    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());

    /* Make player stand up if they're not already stood up and not stunned */
    if (!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED))
        { pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); }

    m_playerLoading = false;

    /* Used for movement */
    m_clientTimeDelay = 0;

    /* Used for looting */
    pCurrChar->lastTimeLooted = time(NULL);

    delete holder;
}
Пример #29
0
void Item::DeleteGiftsFromDB()
{
    static SqlStatementID delGifts;
    SqlStatement stmt = CharacterDatabase.CreateStatement(delGifts, "DELETE FROM character_gifts WHERE item_guid = ?");
    stmt.PExecute(GetGUIDLow());
}
Пример #30
0
bool WorldSocket::HandleAuthSession(WorldPacket &recvPacket)
{
    // NOTE: ATM the socket is singlethread, have this in mind ...
    uint8 digest[20];
    uint32 clientSeed, id, security;
    uint32 ClientBuild;
    LocaleConstant locale;
    std::string account;
    Sha1Hash sha1;
    BigNumber v, s, g, N, K;
    WorldPacket packet, SendAddonPacked;

    // Read the content of the packet
    recvPacket >> ClientBuild;
    recvPacket.read_skip<uint32>();
    recvPacket >> account;
    recvPacket >> clientSeed;
    recvPacket.read(digest, 20);

    DEBUG_LOG("WorldSocket::HandleAuthSession: client build %u, account %s, clientseed %X",
              ClientBuild,
              account.c_str(),
              clientSeed);

    // Check the version of client trying to connect
    if (!IsAcceptableClientBuild(ClientBuild))
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_VERSION_MISMATCH);

        SendPacket(packet);

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch).");
        return false;
    }

    // Get the account information from the realmd database
    std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
    LoginDatabase.escape_string(safe_account);
    // No SQL injection, username escaped.

    QueryResult* result =
        LoginDatabase.PQuery("SELECT "
                             "id, "                      //0
                             "gmlevel, "                 //1
                             "sessionkey, "              //2
                             "last_ip, "                 //3
                             "locked, "                  //4
                             "v, "                       //5
                             "s, "                       //6
                             "mutetime, "                //7
                             "locale "                   //8
                             "FROM account "
                             "WHERE username = '******'",
                             safe_account.c_str());

    // Stop if the account is not found
    if (!result)
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_UNKNOWN_ACCOUNT);

        SendPacket(packet);

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
        return false;
    }

    Field* fields = result->Fetch();

    N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
    g.SetDword(7);

    v.SetHexStr(fields[5].GetString());
    s.SetHexStr(fields[6].GetString());
    m_s = s;

    const char* sStr = s.AsHexStr();                        // Must be freed by OPENSSL_free()
    const char* vStr = v.AsHexStr();                        // Must be freed by OPENSSL_free()

    DEBUG_LOG("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s",
              sStr,
              vStr);

    OPENSSL_free((void*) sStr);
    OPENSSL_free((void*) vStr);

    ///- Re-check ip locking (same check as in realmd).
    if (fields[4].GetUInt8() == 1)  // if ip is locked
    {
        if (strcmp(fields[3].GetString(), GetRemoteAddress().c_str()))
        {
            packet.Initialize(SMSG_AUTH_RESPONSE, 1);
            packet << uint8(AUTH_FAILED);
            SendPacket(packet);

            delete result;
            BASIC_LOG("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs).");
            return false;
        }
    }

    id = fields[0].GetUInt32();
    security = fields[1].GetUInt16();
    if (security > SEC_ADMINISTRATOR)                       // prevent invalid security settings in DB
        security = SEC_ADMINISTRATOR;

    K.SetHexStr(fields[2].GetString());

    time_t mutetime = time_t (fields[7].GetUInt64());

    uint8 tempLoc = LocaleConstant(fields[8].GetUInt8());
    if (tempLoc >= static_cast<uint8>(MAX_LOCALE))
        locale = LOCALE_enUS;
    else
        locale = LocaleConstant(tempLoc);

    delete result;

    // Re-check account ban (same check as in realmd)
    QueryResult* banresult =
        LoginDatabase.PQuery("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)"
                             "UNION "
                             "SELECT 1 FROM ip_banned WHERE (unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'",
                             id, GetRemoteAddress().c_str());

    if (banresult) // if account banned
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_BANNED);
        SendPacket(packet);

        delete banresult;

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
        return false;
    }

    // Check locked state for server
    AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit();

    if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType)
    {
        WorldPacket Packet(SMSG_AUTH_RESPONSE, 1);
        Packet << uint8(AUTH_UNAVAILABLE);

        SendPacket(packet);

        BASIC_LOG("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
        return false;
    }

    // Check that Key and account name are the same on client and server
    Sha1Hash sha;

    uint32 t = 0;
    uint32 seed = m_seed;

    sha.UpdateData(account);
    sha.UpdateData((uint8*) & t, 4);
    sha.UpdateData((uint8*) & clientSeed, 4);
    sha.UpdateData((uint8*) & seed, 4);
    sha.UpdateBigNumbers(&K, nullptr);
    sha.Finalize();

    if (memcmp(sha.GetDigest(), digest, 20))
    {
        packet.Initialize(SMSG_AUTH_RESPONSE, 1);
        packet << uint8(AUTH_FAILED);

        SendPacket(packet);

        sLog.outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed).");
        return false;
    }

    const std::string &address = GetRemoteAddress();

    DEBUG_LOG("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
              account.c_str(),
              address.c_str());

    // Update the last_ip in the database
    // No SQL injection, username escaped.
    static SqlStatementID updAccount;

    SqlStatement stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE account SET last_ip = ? WHERE username = ?");
    stmt.PExecute(address.c_str(), account.c_str());

    if (!(m_session = new WorldSession(id, this, AccountTypes(security), mutetime, locale)))
        return false;

    m_crypt.Init(&K);

    m_session->LoadTutorialsData();

    sWorld.AddSession(m_session);

    // Create and send the Addon packet
    if (sAddOnHandler.BuildAddonPacket(recvPacket, SendAddonPacked))
        SendPacket(SendAddonPacked);

    return true;
}