From 3162a8dc61c3d74f6f5fcd3cc3a3a8563c969809 Mon Sep 17 00:00:00 2001 From: arrai Date: Sat, 1 Nov 2008 16:07:41 +0100 Subject: [PATCH 01/18] Implemented realmd reconnect, backported from 303 branch (cherry picked from commit ac6d01a6b0bf2ffd874db2097ade90ecfd7b1ff7) --- src/realmd/AuthSocket.cpp | 128 +++++++++++++++++++++++++++++++++++--- src/realmd/AuthSocket.h | 3 + 2 files changed, 123 insertions(+), 8 deletions(-) diff --git a/src/realmd/AuthSocket.cpp b/src/realmd/AuthSocket.cpp index 93fc8da0d..987e1d210 100644 --- a/src/realmd/AuthSocket.cpp +++ b/src/realmd/AuthSocket.cpp @@ -43,8 +43,8 @@ enum eAuthCmd //AUTH_NO_CMD = 0xFF, AUTH_LOGON_CHALLENGE = 0x00, AUTH_LOGON_PROOF = 0x01, - //AUTH_RECONNECT_CHALLENGE = 0x02, - //AUTH_RECONNECT_PROOF = 0x03, + AUTH_RECONNECT_CHALLENGE = 0x02, + AUTH_RECONNECT_PROOF = 0x03, //update srv =4 REALM_LIST = 0x10, XFER_INITIATE = 0x30, @@ -131,6 +131,15 @@ typedef struct AUTH_LOGON_PROOF_S uint16 unk3; } sAuthLogonProof_S; +typedef struct AUTH_RECONNECT_PROOF_C +{ + uint8 cmd; + uint8 R1[16]; + uint8 R2[20]; + uint8 R3[20]; + uint8 number_of_keys; +} sAuthReconnectProof_C; + typedef struct XFER_INIT { uint8 cmd; // XFER_INITIATE @@ -196,12 +205,14 @@ class Patcher const AuthHandler table[] = { - { AUTH_LOGON_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleLogonChallenge}, - { AUTH_LOGON_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleLogonProof }, - { REALM_LIST, STATUS_AUTHED, &AuthSocket::_HandleRealmList }, - { XFER_ACCEPT, STATUS_CONNECTED, &AuthSocket::_HandleXferAccept }, - { XFER_RESUME, STATUS_CONNECTED, &AuthSocket::_HandleXferResume }, - { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } + { AUTH_LOGON_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleLogonChallenge }, + { AUTH_LOGON_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleLogonProof }, + { AUTH_RECONNECT_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleReconnectChallenge}, + { AUTH_RECONNECT_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleReconnectProof }, + { REALM_LIST, STATUS_AUTHED, &AuthSocket::_HandleRealmList }, + { XFER_ACCEPT, STATUS_CONNECTED, &AuthSocket::_HandleXferAccept }, + { XFER_RESUME, STATUS_CONNECTED, &AuthSocket::_HandleXferResume }, + { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } }; #define AUTH_TOTAL_COMMANDS sizeof(table)/sizeof(AuthHandler) @@ -707,6 +718,107 @@ bool AuthSocket::_HandleLogonProof() return true; } +/// Reconnect Challenge command handler +bool AuthSocket::_HandleReconnectChallenge() +{ + DEBUG_LOG("Entering _HandleReconnectChallenge"); + if (ibuf.GetLength() < sizeof(sAuthLogonChallenge_C)) + return false; + + ///- Read the first 4 bytes (header) to get the length of the remaining of the packet + std::vector buf; + buf.resize(4); + + ibuf.Read((char *)&buf[0], 4); + + EndianConvert(*((uint16*)(buf[0]))); + uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; + DEBUG_LOG("[ReconnectChallenge] got header, body is %#04x bytes", remaining); + + if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (ibuf.GetLength() < remaining)) + return false; + + //No big fear of memory outage (size is int16, i.e. < 65536) + buf.resize(remaining + buf.size() + 1); + buf[buf.size() - 1] = 0; + sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; + + ///- Read the remaining of the packet + ibuf.Read((char *)&buf[4], remaining); + DEBUG_LOG("[ReconnectChallenge] got full packet, %#04x bytes", ch->size); + DEBUG_LOG("[ReconnectChallenge] name(%d): '%s'", ch->I_len, ch->I); + + _login = (const char*)ch->I; + _safelogin = _login; + + QueryResult *result = dbRealmServer.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ()); + + // Stop if the account is not found + if (!result) + { + sLog.outError("[ERROR] user %s tried to login and we cannot find his session key in the database.", _login.c_str()); + SetCloseAndDelete(); + return false; + } + + Field* fields = result->Fetch (); + K.SetHexStr (fields[0].GetString ()); + delete result; + + ///- Sending response + ByteBuffer pkt; + pkt << (uint8) AUTH_RECONNECT_CHALLENGE; + pkt << (uint8) 0x00; + _reconnectProof.SetRand(16*8); + pkt.append(_reconnectProof.AsByteBuffer()); // 16 bytes random + pkt << (uint64) 0x00 << (uint64) 0x00; // 16 bytes zeros + SendBuf((char const*)pkt.contents(), pkt.size()); + return true; +} + +/// Reconnect Proof command handler +bool AuthSocket::_HandleReconnectProof() +{ + DEBUG_LOG("Entering _HandleReconnectProof"); + ///- Read the packet + if (ibuf.GetLength() < sizeof(sAuthReconnectProof_C)) + return false; + if (_login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) + return false; + sAuthReconnectProof_C lp; + ibuf.Read((char *)&lp, sizeof(sAuthReconnectProof_C)); + + BigNumber t1; + t1.SetBinary(lp.R1, 16); + + Sha1Hash sha; + sha.Initialize(); + sha.UpdateData(_login); + sha.UpdateBigNumbers(&t1, &_reconnectProof, &K, NULL); + sha.Finalize(); + + if (!memcmp(sha.GetDigest(), lp.R2, SHA_DIGEST_LENGTH)) + { + ///- Sending response + ByteBuffer pkt; + pkt << (uint8) AUTH_RECONNECT_PROOF; + pkt << (uint8) 0x00; + pkt << (uint16) 0x00; // 2 bytes zeros + SendBuf((char const*)pkt.contents(), pkt.size()); + + ///- Set _authed to true! + _authed = true; + + return true; + } + else + { + sLog.outError("[ERROR] user %s tried to login, but session invalid.", _login.c_str()); + SetCloseAndDelete(); + return false; + } +} + /// %Realm List command handler bool AuthSocket::_HandleRealmList() { diff --git a/src/realmd/AuthSocket.h b/src/realmd/AuthSocket.h index d67164b5f..b46e1d425 100644 --- a/src/realmd/AuthSocket.h +++ b/src/realmd/AuthSocket.h @@ -47,6 +47,8 @@ class AuthSocket: public TcpSocket bool _HandleLogonChallenge(); bool _HandleLogonProof(); + bool _HandleReconnectChallenge(); + bool _HandleReconnectProof(); bool _HandleRealmList(); //data transfer handle for patch @@ -65,6 +67,7 @@ class AuthSocket: public TcpSocket BigNumber N, s, g, v; BigNumber b, B; BigNumber K; + BigNumber _reconnectProof; bool _authed; From 6f6ec21b724d0f03cf982ad260446a03211fa873 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 21:08:39 +0300 Subject: [PATCH 02/18] Avoid access to bag item prototype for getting bag size, use related item update field instead as more fast source. --- src/game/Bag.cpp | 61 ++++------- src/game/Bag.h | 1 + src/game/Level2.cpp | 6 +- src/game/Player.cpp | 240 +++++++++++++++-------------------------- src/game/debugcmds.cpp | 6 +- 5 files changed, 112 insertions(+), 202 deletions(-) diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index 6345ff4d5..cd6c4d69a 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -37,30 +37,25 @@ Bag::Bag( ): Item() Bag::~Bag() { - for(int i = 0; iAddToWorld(); - } } void Bag::RemoveFromWorld() { - for(int i = 0; iRemoveFromWorld(); - } Item::RemoveFromWorld(); } @@ -109,7 +104,7 @@ bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) return false; // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) - for (uint32 i = 0; i < GetProto()->ContainerSlots; i++) + for (int i = 0; i < MAX_BAG_SIZE; ++i) { SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); if (m_bagslot[i]) @@ -125,21 +120,16 @@ bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) void Bag::DeleteFromDB() { for (int i = 0; i < MAX_BAG_SIZE; i++) - { if (m_bagslot[i]) - { m_bagslot[i]->DeleteFromDB(); - } - } Item::DeleteFromDB(); } uint32 Bag::GetFreeSlots() const { - uint32 ContainerSlots=GetProto()->ContainerSlots; uint32 slots = 0; - for (uint8 i=0; i BuildCreateUpdateBlockForPlayer( data, target ); - } } // If the bag is empty returns true bool Bag::IsEmpty() const { - uint32 ContainerSlots=GetProto()->ContainerSlots; - for(uint32 i=0; i < ContainerSlots; i++) - if (m_bagslot[i]) return false; + for(uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i]) + return false; return true; } uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const { - uint32 ContainerSlots=GetProto()->ContainerSlots; - Item *pItem; uint32 count = 0; - for(uint32 i=0; i < ContainerSlots; i++) + for(uint32 i=0; i < GetBagSize(); ++i) { pItem = m_bagslot[i]; if( pItem && pItem != eItem && pItem->GetEntry() == item ) @@ -208,7 +194,7 @@ uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const if(eItem && eItem->GetProto()->GemProperties) { - for(uint32 i=0; i < ContainerSlots; i++) + for(uint32 i=0; i < GetBagSize(); ++i) { pItem = m_bagslot[i]; if( pItem && pItem != eItem && pItem->GetProto()->Socket[0].Color ) @@ -221,29 +207,18 @@ uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const uint8 Bag::GetSlotByItemGUID(uint64 guid) const { - uint32 ContainerSlots=GetProto()->ContainerSlots; - - for(uint32 i=0;iGetGUID() == guid) return i; - } + return NULL_SLOT; } -// Adds an item to a bag slot -// - slot can be NULL_SLOT, in that case function searchs for a free slot -// - Return values: 0 - item not added -// 1 - item added to a free slot (and perhaps to a stack) -// 2 - item added to a stack (item should be deleted) Item* Bag::GetItemByPos( uint8 slot ) const { - ItemPrototype const *pBagProto = GetProto(); - if( pBagProto ) - { - if( slot < pBagProto->ContainerSlots ) - return m_bagslot[slot]; - } + if( slot < GetBagSize() ) + return m_bagslot[slot]; + return NULL; } diff --git a/src/game/Bag.h b/src/game/Bag.h index 07ae17341..21458546e 100644 --- a/src/game/Bag.h +++ b/src/game/Bag.h @@ -50,6 +50,7 @@ class Bag : public Item uint8 GetSlotByItemGUID(uint64 guid) const; bool IsEmpty() const; uint32 GetFreeSlots() const; + uint32 GetBagSize() const { return GetUInt32Value(CONTAINER_FIELD_NUM_SLOTS); } // DB operations // overwrite virtual Item::SaveToDB diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index bd0f350cf..4ca6c62ae 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -859,12 +859,12 @@ bool ChatHandler::HandleItemMoveCommand(const char* args) srcslot = (uint8)atoi(pParam1); dstslot = (uint8)atoi(pParam2); - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - if(srcslot==dstslot) return true; + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + m_session->GetPlayer()->SwapItem( src, dst ); return true; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 922e45884..493bd232c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3828,10 +3828,9 @@ void Player::DurabilityLossAll(double percent, bool inventory) for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) - if(ItemPrototype const *pBagProto = pBag->GetProto()) - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - if(Item* pItem = GetItemByPos( i, j )) - DurabilityLoss(pItem,percent); + for(uint32 j = 0; j < pBag->GetBagSize(); j++) + if(Item* pItem = GetItemByPos( i, j )) + DurabilityLoss(pItem,percent); } } @@ -3873,10 +3872,9 @@ void Player::DurabilityPointsLossAll(int32 points, bool inventory) for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) - if(ItemPrototype const *pBagProto = pBag->GetProto()) - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - if(Item* pItem = GetItemByPos( i, j )) - DurabilityPointsLoss(pItem,points); + for(uint32 j = 0; j < pBag->GetBagSize(); j++) + if(Item* pItem = GetItemByPos( i, j )) + DurabilityPointsLoss(pItem,points); } } @@ -8009,24 +8007,19 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const } } Bag *pBag; - ItemPrototype const *pBagProto; for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) { - pItem = GetItemByPos( i, j ); - if( pItem && pItem->GetEntry() == item ) - { - tempcount += pItem->GetCount(); - if( tempcount >= count ) - return EQUIP_ERR_OK; - } + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return EQUIP_ERR_OK; } } } @@ -8117,15 +8110,11 @@ Item* Player::GetItemByGuid( uint64 guid ) const Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos( j ); - if( pItem && pItem->GetGUID() == guid ) - return pItem; - } + Item* pItem = pBag->GetItemByPos( j ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; } } } @@ -8134,15 +8123,11 @@ Item* Player::GetItemByGuid( uint64 guid ) const Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos( j ); - if( pItem && pItem->GetGUID() == guid ) - return pItem; - } + Item* pItem = pBag->GetItemByPos( j ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; } } } @@ -8300,17 +8285,14 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - if(ItemPrototype const *pBagProto = pBag->GetProto()) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + Item* pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) { - Item* pItem = GetItemByPos( i, j ); - if( pItem && pItem->GetEntry() == item ) - { - tempcount += pItem->GetCount(); - if( tempcount >= count ) - return true; - } + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; } } } @@ -8332,17 +8314,14 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - if(ItemPrototype const *pBagProto = pBag->GetProto()) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + Item* pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) { - Item* pItem = GetItemByPos( i, j ); - if( pItem && pItem->GetEntry() == item ) - { - tempcount += pItem->GetCount(); - if( tempcount >= count ) - return true; - } + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; } } } @@ -8420,22 +8399,15 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } - Bag *pBag; - ItemPrototype const *pBagProto; for(uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { - pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); - if( pBag ) + if(Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); ++j) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; ++j) - { - pItem = GetItemByPos( i, j ); - if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) - return true; - } + pItem = GetItemByPos( i, j ); + if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) + return true; } } } @@ -8529,7 +8501,7 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy if( !ItemCanGoIntoBag(pProto,pBagProto) ) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot if(j==skip_slot) @@ -9036,23 +9008,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { - Bag *pBag; - ItemPrototype const *pBagProto; - - pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); - if( pBag ) + if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - pBagProto = pBag->GetProto(); - - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem2 = GetItemByPos( i, j ); + if (pItem2 && !pItem2->IsInTrade()) { - pItem2 = GetItemByPos( i, j ); - if (pItem2 && !pItem2->IsInTrade()) - { - inv_bags[i-INVENTORY_SLOT_BAG_START][j] = pItem2->GetCount(); - } + inv_bags[i-INVENTORY_SLOT_BAG_START][j] = pItem2->GetCount(); } } } @@ -9119,18 +9082,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); if( pBag ) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem2 = GetItemByPos( t, j ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable ) { - pItem2 = GetItemByPos( t, j ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable ) - { - inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); - b_found = true; - break; - } + inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); + b_found = true; + break; } } } @@ -9169,7 +9128,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const if( pBagProto && (pBagProto->Class != ITEM_CLASS_CONTAINER || pBagProto->SubClass != ITEM_SUBCLASS_CONTAINER) && ItemCanGoIntoBag(pProto,pBagProto) ) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) { @@ -9203,17 +9162,13 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); if( pBag ) { - pBagProto = pBag->GetProto(); - if( pBagProto && ItemCanGoIntoBag(pProto,pBagProto)) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) { - if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) - { - inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1; - b_found = true; - break; - } + inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1; + b_found = true; + break; } } } @@ -10307,40 +10262,33 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq } // in inventory bags - Bag *pBag; - ItemPrototype const *pBagProto; for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { - pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); - if( pBag ) + if(Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetEntry() == item ) { - pItem = pBag->GetItemByPos(j); - if( pItem && pItem->GetEntry() == item ) + // all items in bags can be unequipped + if( pItem->GetCount() + remcount <= count ) { - // all items in bags can be unequipped - if( pItem->GetCount() + remcount <= count ) - { - remcount += pItem->GetCount(); - DestroyItem( i, j, update ); + remcount += pItem->GetCount(); + DestroyItem( i, j, update ); - if(remcount >=count) - return; - } - else - { - pProto = pItem->GetProto(); - ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); - pItem->SetCount( pItem->GetCount() - count + remcount ); - if( IsInWorld() && update ) - pItem->SendUpdateToPlayer( this ); - pItem->SetState(ITEM_CHANGED, this); + if(remcount >=count) return; - } + } + else + { + pProto = pItem->GetProto(); + ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); + pItem->SetCount( pItem->GetCount() - count + remcount ); + if( IsInWorld() && update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + return; } } } @@ -10402,15 +10350,11 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone ) Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos(j); - if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) - DestroyItem( i, j, update); - } + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) + DestroyItem( i, j, update); } } } @@ -10446,17 +10390,13 @@ void Player::DestroyConjuredItems( bool update ) Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos(j); - if( pItem && pItem->GetProto() && - (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && - (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) - DestroyItem( i, j, update); - } + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetProto() && + (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && + (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) + DestroyItem( i, j, update); } } } @@ -11104,15 +11044,11 @@ void Player::RemoveAllEnchantments(EnchantmentSlot slot) Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos(j); - if( pItem && pItem->GetEnchantmentId(slot) ) - pItem->ClearEnchantment(slot); - } + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetEnchantmentId(slot) ) + pItem->ClearEnchantment(slot); } } } diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 83754be27..df5e4348b 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -319,8 +319,7 @@ bool ChatHandler::HandleGetItemState(const char* args) else { Bag *bag = (Bag*)item; - const ItemPrototype *proto = bag->GetProto(); - for (uint8 j = 0; j < proto->ContainerSlots; ++j) + for (uint8 j = 0; j < bag->GetBagSize(); ++j) { Item* item = bag->GetItemByPos(j); if (item && item->GetState() == state) @@ -416,8 +415,7 @@ bool ChatHandler::HandleGetItemState(const char* args) if(item->IsBag()) { Bag *bag = (Bag*)item; - const ItemPrototype *proto = bag->GetProto(); - for (uint8 j = 0; j < proto->ContainerSlots; ++j) + for (uint8 j = 0; j < bag->GetBagSize(); ++j) { Item* item = bag->GetItemByPos(j); if (!item) continue; From d54e53c709f30a321b778d41ae7b3c4b4181089a Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 21:18:36 +0300 Subject: [PATCH 03/18] Better check client inventory pos data received in some client packets to skip invalid cases. --- src/game/ItemHandler.cpp | 42 +++++++++++++++++++++++ src/game/Level2.cpp | 6 ++++ src/game/Player.cpp | 72 ++++++++++++++++++++++++++++++++++++++++ src/game/Player.h | 2 ++ 4 files changed, 122 insertions(+) diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 04355c85d..9396b8633 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -47,6 +47,18 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) if (count==0) return; //check count - if zero it's fake packet + if(!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + _player->SplitItem( src, dst, count ); } @@ -64,6 +76,18 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data ) if(srcslot==dstslot) return; + if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + uint16 src = ( (INVENTORY_SLOT_BAG_0 << 8) | srcslot ); uint16 dst = ( (INVENTORY_SLOT_BAG_0 << 8) | dstslot ); @@ -107,6 +131,18 @@ void WorldSession::HandleSwapItem( WorldPacket & recv_data ) if(src==dst) return; + if(!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + _player->SwapItem( src, dst ); } @@ -747,6 +783,12 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data ) if( !pItem ) return; + if(!_player->IsValidPos(dstbag,NULL_SLOT)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + uint16 src = pItem->GetPos(); // check unequip potability for equipped items and bank bags diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 4ca6c62ae..b53b569b8 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -862,6 +862,12 @@ bool ChatHandler::HandleItemMoveCommand(const char* args) if(srcslot==dstslot) return true; + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 493bd232c..74a71742c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -8258,6 +8258,78 @@ bool Player::IsBagPos( uint16 pos ) return false; } +bool Player::IsValidPos( uint8 bag, uint8 slot ) +{ + // post selected + if(bag == NULL_BAG) + return true; + + if (bag == INVENTORY_SLOT_BAG_0) + { + // any post selected + if (slot == NULL_SLOT) + return true; + + // equipment + if (slot < EQUIPMENT_SLOT_END) + return true; + + // bag equip slots + if (slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END) + return true; + + // backpack slots + if (slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END) + return true; + + // keyring slots + if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END) + return true; + + // bank main slots + if (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END) + return true; + + // bank bag slots + if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END) + return true; + + return false; + } + + // bag content slots + if (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END) + { + Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag); + if(!pBag) + return false; + + // any post selected + if (slot == NULL_SLOT) + return true; + + return slot < pBag->GetBagSize(); + } + + // bank bag content slots + if( bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) + { + Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag); + if(!pBag) + return false; + + // any post selected + if (slot == NULL_SLOT) + return true; + + return slot < pBag->GetBagSize(); + } + + // where this? + return false; +} + + bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { uint32 tempcount = 0; diff --git a/src/game/Player.h b/src/game/Player.h index aaaaac60f..ca6e50bd9 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1037,6 +1037,8 @@ class MANGOS_DLL_SPEC Player : public Unit static bool IsBagPos( uint16 pos ); static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } static bool IsBankPos( uint8 bag, uint8 slot ); + bool IsValidPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } + bool IsValidPos( uint8 bag, uint8 slot ); bool HasBankBagSlot( uint8 slot ) const; bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL); From 63a35e388a691d231b74ee33653650597da186ea Mon Sep 17 00:00:00 2001 From: derex Date: Sat, 1 Nov 2008 21:21:12 +0200 Subject: [PATCH 04/18] Restore build on FreeBSD. --- dep/ACE_wrappers/ace/OS_NS_netdb.inl | 10 +++++----- dep/ACE_wrappers/ace/os_include/os_signal.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dep/ACE_wrappers/ace/OS_NS_netdb.inl b/dep/ACE_wrappers/ace/OS_NS_netdb.inl index f1d0009ee..58ebc0c1f 100644 --- a/dep/ACE_wrappers/ace/OS_NS_netdb.inl +++ b/dep/ACE_wrappers/ace/OS_NS_netdb.inl @@ -125,7 +125,7 @@ ACE_OS::gethostbyaddr_r (const char *addr, *h_errnop = h_errno; return (struct hostent *) 0; } -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); @@ -318,7 +318,7 @@ ACE_OS::gethostbyname_r (const char *name, *h_errnop = h_errno; return (struct hostent *) 0; } -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); @@ -528,7 +528,7 @@ ACE_OS::getprotobyname_r (const char *name, else return 0; //FUZZ: enable check_for_lack_ACE_OS -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature //FUZZ: disable check_for_lack_ACE_OS if (::getprotobyname_r (name, @@ -609,7 +609,7 @@ ACE_OS::getprotobynumber_r (int proto, //FUZZ: enable check_for_lack_ACE_OS else return 0; -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature //FUZZ: disable check_for_lack_ACE_OS if (::getprotobynumber_r (proto, @@ -695,7 +695,7 @@ ACE_OS::getservbyname_r (const char *svc, //FUZZ: enable check_for_lack_ACE_OS else return (struct servent *) 0; -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature ACE_OS::memset (buf, 0, sizeof (ACE_SERVENT_DATA)); diff --git a/dep/ACE_wrappers/ace/os_include/os_signal.h b/dep/ACE_wrappers/ace/os_include/os_signal.h index fdfd21e99..957450601 100644 --- a/dep/ACE_wrappers/ace/os_include/os_signal.h +++ b/dep/ACE_wrappers/ace/os_include/os_signal.h @@ -25,6 +25,7 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/os_include/sys/os_types.h" +#include "ace/os_include/os_pthread.h" #if !defined (ACE_LACKS_SIGNAL_H) extern "C" { From 715df4e28cd874448630a2e3c2730a154e848dce Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 1 Nov 2008 08:42:49 +0300 Subject: [PATCH 05/18] No real changes (cherry picked from commit 80e8f17627db58b3d275407547687aec6d10362b) --- src/game/Level2.cpp | 1 - src/game/QueryHandler.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index b53b569b8..ca996bd7c 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4208,7 +4208,6 @@ bool ChatHandler::HandleNpcTameCommand(const char* args) // set pet to defensive mode by default (some classes can't control contolled pets in fact). pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); - // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 713338c51..0c3ad1f04 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -96,7 +96,7 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 else field = fields[2].GetUInt32(); - // guess size + // guess size WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) ); data << MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER); data << name; @@ -179,7 +179,7 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty data << SubName; data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 - data << (uint32)ci->type_flags; // flags wdbFeild7=wad flags1 + data << (uint32)ci->type_flags; // flags wdbFeild7=wad flags1 data << (uint32)ci->type; data << (uint32)ci->family; // family wdbFeild9 data << (uint32)ci->rank; // rank wdbFeild10 From 8563b88859451360cf6d3dedfb3989e767fa8d75 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 23:53:35 +0300 Subject: [PATCH 06/18] Fixed some format arg type/value pairs. Other warnings. --- src/game/BattleGround.cpp | 4 ++-- src/game/BattleGroundBE.cpp | 2 +- src/game/BattleGroundEY.cpp | 5 +++-- src/game/BattleGroundMgr.cpp | 2 +- src/game/BattleGroundRL.cpp | 2 +- src/game/BattleGroundWS.cpp | 2 +- src/game/CharacterHandler.cpp | 3 ++- src/game/Corpse.cpp | 6 ++++-- src/game/Level2.cpp | 9 ++------- src/game/LootMgr.cpp | 3 ++- src/game/MiscHandler.cpp | 4 ++-- src/game/MotionMaster.cpp | 1 + src/game/NPCHandler.cpp | 5 +++-- src/game/Pet.cpp | 5 +++-- src/shared/Database/SqlOperations.cpp | 3 ++- 15 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index dd199e2ed..00db60b4f 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -997,7 +997,7 @@ bool BattleGround::DelCreature(uint32 type) Creature *cr = HashMapHolder::Find(m_BgCreatures[type]); if(!cr) { - sLog.outError("Can't find creature guid: %u",m_BgCreatures[type]); + sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type])); return false; } cr->CleanupsBeforeDelete(); @@ -1011,7 +1011,7 @@ bool BattleGround::DelObject(uint32 type) GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); if(!obj) { - sLog.outError("Can't find gobject guid: %u",m_BgObjects[type]); + sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type])); return false; } obj->SetRespawnTime(0); // not save respawn time diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index dcf994325..4ad71988e 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -104,7 +104,7 @@ void BattleGroundBE::AddPlayer(Player *plr) m_PlayerScores[plr->GetGUID()] = sc; } -void BattleGroundBE::RemovePlayer(Player *plr, uint64 guid) +void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { } diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 165b1cf42..5eb6d6286 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -556,7 +556,7 @@ void BattleGroundEY::RespawnFlagAfterDrop() if(obj) obj->Delete(); else - sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GetDroppedFlagGUID()); + sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GUID_LOPART(GetDroppedFlagGUID())); SetDroppedFlagGUID(0); } @@ -741,7 +741,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) WorldSafeLocsEntry const *sg = NULL; sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId); if(!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team)) - sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: u, graveyard_id: %u", Point, Team, m_CapturingPointTypes[Point].GraveYardId); + sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", + Point, Team, m_CapturingPointTypes[Point].GraveYardId); UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 5bd23ceef..046f18b48 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -341,7 +341,7 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) /*** BATTLEGROUND QUEUE EVENTS ***/ /*********************************************************/ -bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 p_time) +bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { Player* plr = objmgr.GetPlayer( m_PlayerGuid ); diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 130f46a63..4be135c70 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -98,7 +98,7 @@ void BattleGroundRL::AddPlayer(Player *plr) m_PlayerScores[plr->GetGUID()] = sc; } -void BattleGroundRL::RemovePlayer(Player *plr, uint64 guid) +void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { } diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index c482a959e..4334304d6 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -198,7 +198,7 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) if(obj) obj->Delete(); else - sLog.outError("unknown droped flag bg, guid: %u",GetDroppedFlagGUID(team)); + sLog.outError("unknown droped flag bg, guid: %u",GUID_LOPART(GetDroppedFlagGUID(team))); SetDroppedFlagGUID(0,team); } diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 0507ef53c..78e19a814 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -749,7 +749,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); - sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUID()); + sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)", + GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); m_playerLoading = false; delete holder; diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index 6b298791d..c2a873a1b 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -79,7 +79,8 @@ bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float if(!IsPositionValid()) { - sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",guidlow,owner->GetName(),x,y); + sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow,owner->GetName(),x,y); return false; } @@ -196,7 +197,8 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) if(!IsPositionValid()) { - sLog.outError("ERROR: Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",GetGUIDLow(),GUID_LOPART(GetOwnerGUID()),GetPositionX(),GetPositionY()); + sLog.outError("ERROR: Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(),GUID_LOPART(GetOwnerGUID()),GetPositionX(),GetPositionY()); return false; } diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index ca996bd7c..fb07a793f 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -2861,12 +2861,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) std::string show = show_str; uint32 Maxpoint; - sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u", lowguid); - - sLog.outDebug("DEBUG: HandleWpShowCommand: Habe creature: %ld", target ); - - sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str); - //PSendSysMessage("wpshow - show: %s", show); + sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str); // Show info for the selected waypoint if(show == "info") @@ -2887,7 +2882,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) QueryResult *result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u", - target->GetGUID() ); + target->GetGUIDLow() ); if(!result) { // Since we compare float values, we have to deal with diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index c19535ccd..b88169161 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -268,7 +268,8 @@ bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const if( chance != 0 && chance < 0.000001f ) // loot with low chance { - sLog.outErrorDb("Table '%s' entry %d item %d: low chance (%d) - skipped", store.GetName(), entry, itemid, chance); + sLog.outErrorDb("Table '%s' entry %d item %d: low chance (%f) - skipped", + store.GetName(), entry, itemid, chance); return false; } } diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 238bfa883..414ec89c8 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -132,7 +132,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) wstrToLower(str[i]); - sLog.outDebug("String %u: %s", i, str[i].c_str()); + sLog.outDebug("String %u: %s", i, temp.c_str()); } std::wstring wplayer_name; @@ -966,7 +966,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) (fabs(rotateDy) > atEntry->box_y/2 + delta) || (fabs(dz) > atEntry->box_z/2 + delta) ) { - sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %u 1/2 box Z: %u rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u", + sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u", pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotateDx, rotateDy, dz, Trigger_ID); return; } diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 0ebb40cd6..2dc42cd4d 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -186,6 +186,7 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle) if(i_owner->GetTypeId()==TYPEID_PLAYER) { DEBUG_LOG("Player (GUID: %u) chase to %s (GUID: %u)", + i_owner->GetGUIDLow(), target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() ); Mutate(new TargetedMovementGenerator(*target,dist,angle)); diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 076ec192a..456539e18 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -137,14 +137,15 @@ void WorldSession::SendTrainerList( uint64 guid,std::string strTitle ) if (!ci) { - sLog.outDebug( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)", uint32(GUID_LOPART(guid)), guid ); + sLog.outDebug( "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid) ); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if(!trainer_spells) { - sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", guid, unit->GetEntry()); + sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", + GUID_LOPART(guid), unit->GetEntry()); return; } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 9f9f12d6d..ae190fb4d 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -185,7 +185,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu if(!IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %d Y: ^%d)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); delete result; return false; } @@ -202,7 +203,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu delete result; return true; } - if(getPetType()==HUNTER_PET || getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK) + if(getPetType()==HUNTER_PET || (getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)) m_charmInfo->SetPetNumber(pet_number, true); else m_charmInfo->SetPetNumber(pet_number, false); diff --git a/src/shared/Database/SqlOperations.cpp b/src/shared/Database/SqlOperations.cpp index 0993551cb..bc75c591e 100644 --- a/src/shared/Database/SqlOperations.cpp +++ b/src/shared/Database/SqlOperations.cpp @@ -100,7 +100,8 @@ bool SqlQueryHolder::SetQuery(size_t index, const char *sql) if(m_queries[index].first != NULL) { - sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",index,m_queries.size(),m_queries[index].first,sql); + sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])", + index,m_queries[index].first,sql); return false; } From f2852a95b71500c7f8c88ad773375c0675a82b88 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 15:58:24 +0100 Subject: [PATCH 07/18] Removed some unnecessary database queries. Removed unnecessary database queries in some command handlers. Replaced them with access to cached data or queries for only the needed data. Move database access in gossip select code to less often called place. --- src/game/Creature.cpp | 14 ++++---- src/game/Level2.cpp | 29 ++++++++++++---- src/game/Level3.cpp | 81 ++++++++++++++++++++++--------------------- 3 files changed, 73 insertions(+), 51 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index ce5d9f797..899a7abed 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -818,18 +818,20 @@ void Creature::OnGossipSelect(Player* player, uint32 option) return; } - uint32 textid=GetGossipTextId( action, zoneid); - if(textid==0) - textid=GetNpcTextId(); - switch (gossip->Action) { case GOSSIP_OPTION_GOSSIP: + { + uint32 textid = GetGossipTextId(action, zoneid); + if (textid == 0) + textid=GetNpcTextId(); + player->PlayerTalkClass->CloseGossip(); - player->PlayerTalkClass->SendTalking( textid ); + player->PlayerTalkClass->SendTalking(textid); break; + } case GOSSIP_OPTION_SPIRITHEALER: - if( player->isDead() ) + if (player->isDead()) CastSpell(this,17251,true,NULL,NULL,player->GetGUID()); break; case GOSSIP_OPTION_QUESTGIVER: diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index fb07a793f..55f8f25ab 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -1799,13 +1799,30 @@ bool ChatHandler::HandlePInfoCommand(const char* args) // get additional information from DB else { + // 0 + QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", targetGUID); + if (!result) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + total_player_time = fields[0].GetUInt32(); + delete result; + + Tokens data; + if (!Player::LoadValuesArrayFromDB(data,targetGUID)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE); + level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL); + accId = objmgr.GetPlayerAccountIdByGUID(targetGUID); - WorldSession session(0,NULL,SEC_PLAYER,0,0,LOCALE_enUS); - Player plr(&session); // use fake session for temporary load - plr.MinimalLoadFromDB(NULL, targetGUID); - money = plr.GetMoney(); - total_player_time = plr.GetTotalPlayedTime(); - level = plr.getLevel(); } std::string username = GetMangosString(LANG_ERROR); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index ad5e93558..ed8fccf03 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1988,9 +1988,39 @@ bool ChatHandler::HandleAddItemSetCommand(const char* args) sLog.outDetail(GetMangosString(LANG_ADDITEMSET), itemsetId); - QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE itemset = %u",itemsetId); + bool found = false; + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; - if(!result) + if (pProto->ItemSet == itemsetId) + { + found = true; + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pProto->ItemId, 1 ); + if (msg == EQUIP_ERR_OK) + { + Item* item = plTarget->StoreNewItem( dest, pProto->ItemId, true); + + // remove binding (let GM give it to another player later) + if (pl==plTarget) + item->SetBinding( false ); + + pl->SendNewItem(item,1,false,true); + if (pl!=plTarget) + plTarget->SendNewItem(item,1,true,false); + } + else + { + pl->SendEquipError( msg, NULL, NULL ); + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, pProto->ItemId, 1); + } + } + } + + if (!found) { PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); @@ -1998,35 +2028,6 @@ bool ChatHandler::HandleAddItemSetCommand(const char* args) return false; } - do - { - Field *fields = result->Fetch(); - uint32 itemId = fields[0].GetUInt32(); - - ItemPosCountVec dest; - uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, 1 ); - if( msg == EQUIP_ERR_OK ) - { - Item* item = plTarget->StoreNewItem( dest, itemId, true); - - // remove binding (let GM give it to another player later) - if(pl==plTarget) - item->SetBinding( false ); - - pl->SendNewItem(item,1,false,true); - if(pl!=plTarget) - plTarget->SendNewItem(item,1,true,false); - } - else - { - pl->SendEquipError( msg, NULL, NULL ); - PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, 1); - } - - }while( result->NextRow() ); - - delete result; - return true; } @@ -4678,16 +4679,18 @@ bool ChatHandler::HandleAddQuest(const char* args) } // check item starting quest (it can work incorrectly if added without item in inventory) - QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE startquest = '%u' LIMIT 1",entry); - if(result) + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) { - Field* fields = result->Fetch(); - uint32 item_id = fields[0].GetUInt32(); - delete result; + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; - PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry,item_id); - SetSentErrorMessage(true); - return false; + if (pProto->StartQuest == entry) + { + PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, pProto->ItemId); + SetSentErrorMessage(true); + return false; + } } // ok, normal (creature/GO starting) quest From c6eadf5565c5976fa3a8e10598b9ca56803359f0 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 17:53:27 +0100 Subject: [PATCH 08/18] Do not split self caused damage. Do not split damage that is caused by yourself (mainly environmental damage). This also fixes pets attacking their master when SL is active. --- src/game/Unit.cpp | 76 +++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 4a247daa0..7e68980b9 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1652,56 +1652,60 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe RemainingDamage -= currentAbsorb; } - AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); - for(AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) + // only split damage if not damaing yourself + if(pVictim != this) { - next = i; ++next; + AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); + for(AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) + { + next = i; ++next; - // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) - continue; + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; - // Damage can be splitted only if aura has an alive caster - Unit *caster = (*i)->GetCaster(); - if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) - continue; + // Damage can be splitted only if aura has an alive caster + Unit *caster = (*i)->GetCaster(); + if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) + continue; - int32 currentAbsorb; - if (RemainingDamage >= (*i)->GetModifier()->m_amount) - currentAbsorb = (*i)->GetModifier()->m_amount; - else - currentAbsorb = RemainingDamage; + int32 currentAbsorb; + if (RemainingDamage >= (*i)->GetModifier()->m_amount) + currentAbsorb = (*i)->GetModifier()->m_amount; + else + currentAbsorb = RemainingDamage; - RemainingDamage -= currentAbsorb; + RemainingDamage -= currentAbsorb; - SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false); + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false); - CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); - } + CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + } - AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); - for(AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) - { - next = i; ++next; + AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); + for(AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) + { + next = i; ++next; - // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) - continue; + // check damage school mask + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + continue; - // Damage can be splitted only if aura has an alive caster - Unit *caster = (*i)->GetCaster(); - if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) - continue; + // Damage can be splitted only if aura has an alive caster + Unit *caster = (*i)->GetCaster(); + if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) + continue; - int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); + int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); - RemainingDamage -= splitted; + RemainingDamage -= splitted; - SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); - CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + } } *absorb = damage - RemainingDamage - *resist; From e9fc699d86113f2bfb665106a8c12f39fcb1e0d5 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 20:23:25 +0100 Subject: [PATCH 09/18] Make guid lookup for adding ignore async. --- src/game/CharacterHandler.cpp | 2 +- src/game/MiscHandler.cpp | 58 +++++++++++++++++------------------ src/game/SocialMgr.cpp | 2 +- src/game/SocialMgr.h | 2 +- src/game/WorldSession.cpp | 2 +- src/game/WorldSession.h | 1 + 6 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 78e19a814..700f4f858 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -634,7 +634,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) } // friend status - sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), "", true); + sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 414ec89c8..95dd7b924 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -704,7 +704,7 @@ void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: %s Guid not found.", friendName.c_str() ); } - sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), friendName, false); + sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); } @@ -721,7 +721,7 @@ void WorldSession::HandleDelFriendOpcode( WorldPacket & recv_data ) _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); - sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), "", false); + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); sLog.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" ); } @@ -733,8 +733,6 @@ void WorldSession::HandleAddIgnoreOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: Received CMSG_ADD_IGNORE" ); std::string IgnoreName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); - FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; - uint64 IgnoreGuid = 0; recv_data >> IgnoreName; @@ -746,40 +744,40 @@ void WorldSession::HandleAddIgnoreOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: %s asked to Ignore: '%s'", GetPlayer()->GetName(), IgnoreName.c_str() ); - IgnoreGuid = objmgr.GetPlayerGUIDByName(IgnoreName); + CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddIgnoreOpcodeCallBack, GetAccountId(), "SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str()); +} +void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult *result, uint32 accountId) +{ + if(!result) + return; + + uint64 IgnoreGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + delete result; + + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + return; + + FriendsResult ignoreResult = FRIEND_IGNORE_NOT_FOUND; if(IgnoreGuid) { - if(IgnoreGuid==GetPlayer()->GetGUID()) + if(IgnoreGuid==session->GetPlayer()->GetGUID()) //not add yourself ignoreResult = FRIEND_IGNORE_SELF; + else if( session->GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)) ) + ignoreResult = FRIEND_IGNORE_ALREADY; else { - if( GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)) ) - ignoreResult = FRIEND_IGNORE_ALREADY; + ignoreResult = FRIEND_IGNORE_ADDED; + + // ignore list full + if(!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) + ignoreResult = FRIEND_IGNORE_FULL; } } - if (IgnoreGuid && ignoreResult == FRIEND_IGNORE_NOT_FOUND) - { - ignoreResult = FRIEND_IGNORE_ADDED; - - if(!_player->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) - ignoreResult = FRIEND_IGNORE_FULL; - } - else if(ignoreResult==FRIEND_IGNORE_ALREADY) - { - sLog.outDebug( "WORLD: %s Guid Already Ignored.", IgnoreName.c_str() ); - } - else if(ignoreResult==FRIEND_IGNORE_SELF) - { - sLog.outDebug( "WORLD: %s Guid can't add himself.", IgnoreName.c_str() ); - } - else - { - sLog.outDebug( "WORLD: %s Guid not found.", IgnoreName.c_str() ); - } - - sSocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), "", false); + sSocialMgr.SendFriendStatus(session->GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); } @@ -796,7 +794,7 @@ void WorldSession::HandleDelIgnoreOpcode( WorldPacket & recv_data ) _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); - sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), "", false); + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); sLog.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" ); } diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp index cdb2c3919..6973bc352 100644 --- a/src/game/SocialMgr.cpp +++ b/src/game/SocialMgr.cpp @@ -235,7 +235,7 @@ void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldP *data << uint64(guid); } -void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast) +void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, bool broadcast) { FriendInfo fi; diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h index c4a19295a..8c873d8a0 100644 --- a/src/game/SocialMgr.h +++ b/src/game/SocialMgr.h @@ -145,7 +145,7 @@ class SocialMgr void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo); // Packet management void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data); - void SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, std::string name, bool broadcast); + void SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, bool broadcast); void BroadcastToFriendListers(Player *player, WorldPacket *packet); // Loading PlayerSocial *LoadFromDB(QueryResult *result, uint32 guid); diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 3018f1eb1..59e236c24 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -373,7 +373,7 @@ void WorldSession::LogoutPlayer(bool Save) _player->GetGroup()->SendUpdate(); ///- Broadcast a logout message to the player's friends - sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), "", true); + sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); ///- Delete the player object _player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index aebc44903..e0ad26567 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -281,6 +281,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleAddFriendOpcode(WorldPacket& recvPacket); void HandleDelFriendOpcode(WorldPacket& recvPacket); void HandleAddIgnoreOpcode(WorldPacket& recvPacket); + static void HandleAddIgnoreOpcodeCallBack(QueryResult *result, uint32 accountId); void HandleDelIgnoreOpcode(WorldPacket& recvPacket); void HandleSetFriendNoteOpcode(WorldPacket& recvPacket); void HandleBugOpcode(WorldPacket& recvPacket); From c8bd17f67bd29904519ae96ffc6db4dd607d786d Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sun, 2 Nov 2008 22:20:05 +0200 Subject: [PATCH 10/18] Added two parameter versions of the AsyncQuery function --- src/shared/Database/Database.h | 8 ++++ src/shared/Database/DatabaseImpl.h | 66 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index 3fd319ffe..2d4ee6181 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -59,14 +59,22 @@ class MANGOS_DLL_SPEC Database bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql); template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); + template + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); template bool AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); + template + bool AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); template bool AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); template bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder); template diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index cc8842018..d3eae749a 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -45,6 +45,18 @@ Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamTyp return true; } +template +bool +Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) +{ + if (!sql) return false; + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); + QueryQueues::iterator itr = m_queryQueues.find(queryThread); + if (itr == m_queryQueues.end()) return false; + m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2), itr->second)); + return true; +} + template bool Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql) @@ -57,6 +69,18 @@ Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1 return true; } +template +bool +Database::AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) +{ + if (!sql) return false; + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); + QueryQueues::iterator itr = m_queryQueues.find(queryThread); + if (itr == m_queryQueues.end()) return false; + m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2), itr->second)); + return true; +} + template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) @@ -99,6 +123,27 @@ Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamTy return AsyncQuery(object, method, param1, szQuery); } +template +bool +Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) +{ + if(!format) return false; + + va_list ap; + char szQuery [MAX_QUERY_LEN]; + va_start(ap, format); + int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); + va_end(ap); + + if(res==-1) + { + sLog.outError("SQL Query truncated (and not execute) for format: %s",format); + return false; + } + + return AsyncQuery(object, method, param1, param2, szQuery); +} + template bool Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) @@ -120,6 +165,27 @@ Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param return AsyncQuery(method, param1, szQuery); } +template +bool +Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) +{ + if(!format) return false; + + va_list ap; + char szQuery [MAX_QUERY_LEN]; + va_start(ap, format); + int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); + va_end(ap); + + if(res==-1) + { + sLog.outError("SQL Query truncated (and not execute) for format: %s",format); + return false; + } + + return AsyncQuery(method, param1, param2, szQuery); +} + template bool Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder) From 1a39f30335f6bf05c567392d2a179aecc0e99f5e Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 22:19:41 +0100 Subject: [PATCH 11/18] Make queries for adding friends async. --- src/game/MiscHandler.cpp | 72 +++++++++++++++++++--------------------- src/game/WorldSession.h | 1 + 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 95dd7b924..68a502d2d 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -640,11 +640,8 @@ void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: Received CMSG_ADD_FRIEND" ); - std::string friendName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); + std::string friendName = GetMangosString(LANG_FRIEND_IGNORE_UNKNOWN); std::string friendNote; - FriendsResult friendResult = FRIEND_NOT_FOUND; - Player *pFriend = NULL; - uint64 friendGuid = 0; recv_data >> friendName; @@ -661,50 +658,51 @@ void WorldSession::HandleAddFriendOpcode( WorldPacket & recv_data ) sLog.outDebug( "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName(), friendName.c_str() ); - friendGuid = objmgr.GetPlayerGUIDByName(friendName); + CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race FROM characters WHERE name = '%s'", friendName.c_str()); +} +void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult *result, uint32 accountId, std::string friendNote) +{ + if(!result) + return; + + uint64 friendGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + uint32 team = Player::TeamForRace((*result)[1].GetUInt8()); + + delete result; + + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + return; + + FriendsResult friendResult = FRIEND_NOT_FOUND; if(friendGuid) { - pFriend = ObjectAccessor::FindPlayer(friendGuid); - if(pFriend==GetPlayer()) + if(friendGuid==session->GetPlayer()->GetGUID()) friendResult = FRIEND_SELF; - else if(GetPlayer()->GetTeam()!=objmgr.GetPlayerTeamByGUID(friendGuid) && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && GetSecurity() < SEC_MODERATOR) + else if(session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR) friendResult = FRIEND_ENEMY; - else if(GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) + else if(session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) friendResult = FRIEND_ALREADY; - } - - if (friendGuid && friendResult==FRIEND_NOT_FOUND) - { - if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer())) - friendResult = FRIEND_ADDED_ONLINE; else - friendResult = FRIEND_ADDED_OFFLINE; - - if(!_player->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) { - friendResult = FRIEND_LIST_FULL; - sLog.outDebug( "WORLD: %s's friend list is full.", GetPlayer()->GetName()); + Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); + if( pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer())) + friendResult = FRIEND_ADDED_ONLINE; + else + friendResult = FRIEND_ADDED_OFFLINE; + + if(!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) + { + friendResult = FRIEND_LIST_FULL; + sLog.outDebug( "WORLD: %s's friend list is full.", session->GetPlayer()->GetName()); + } + + session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); } - - _player->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); - - sLog.outDebug( "WORLD: %s Guid found '%u'.", friendName.c_str(), GUID_LOPART(friendGuid)); - } - else if(friendResult==FRIEND_ALREADY) - { - sLog.outDebug( "WORLD: %s Guid Already a Friend.", friendName.c_str() ); - } - else if(friendResult==FRIEND_SELF) - { - sLog.outDebug( "WORLD: %s Guid can't add himself.", friendName.c_str() ); - } - else - { - sLog.outDebug( "WORLD: %s Guid not found.", friendName.c_str() ); } - sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); + sSocialMgr.SendFriendStatus(session->GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); sLog.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" ); } diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index e0ad26567..bf7e5c0a0 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -279,6 +279,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleEmoteOpcode(WorldPacket& recvPacket); void HandleFriendListOpcode(WorldPacket& recvPacket); void HandleAddFriendOpcode(WorldPacket& recvPacket); + static void HandleAddFriendOpcodeCallBack(QueryResult *result, uint32 accountId, std::string friendNote); void HandleDelFriendOpcode(WorldPacket& recvPacket); void HandleAddIgnoreOpcode(WorldPacket& recvPacket); static void HandleAddIgnoreOpcodeCallBack(QueryResult *result, uint32 accountId); From 086dee05cd80a78ecf83f9543fa531aa15510996 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sun, 2 Nov 2008 23:27:03 +0200 Subject: [PATCH 12/18] Added a missing include in MiscHandler.cpp --- src/game/MiscHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 68a502d2d..4bdbbd31b 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "Language.h" #include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" #include "WorldPacket.h" #include "Opcodes.h" #include "Log.h" From fa37c291d6a995c7668aef7b962b289cdb5a0b1f Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 23:22:18 +0100 Subject: [PATCH 13/18] Replace some PQuery() calls with more simple Query() --- src/game/CharacterHandler.cpp | 2 +- src/game/InstanceSaveMgr.cpp | 12 ++++++------ src/game/Level2.cpp | 2 +- src/game/ObjectMgr.cpp | 22 +++++++++++----------- src/game/SkillDiscovery.cpp | 2 +- src/game/SkillExtraItems.cpp | 2 +- src/game/SpellMgr.cpp | 4 ++-- src/game/Transports.cpp | 2 +- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 700f4f858..ef4d358a4 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -309,7 +309,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) bool have_same_race = false; if(!AllowTwoSideAccounts || skipCinematics == 1) { - QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); + QueryResult *result2 = CharacterDatabase.Query("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index 21aff8093..1debe2491 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -268,7 +268,7 @@ void InstanceSaveManager::CleanupInstances() // creature_respawn and gameobject_respawn are in another database // first, obtain total instance set std::set< uint32 > InstanceSet; - QueryResult *result = CharacterDatabase.PQuery("SELECT id FROM instance"); + QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance"); if( result ) { do @@ -281,7 +281,7 @@ void InstanceSaveManager::CleanupInstances() } // creature_respawn - result = WorldDatabase.PQuery("SELECT DISTINCT(instance) FROM creature_respawn WHERE instance <> 0"); + result = WorldDatabase.Query("SELECT DISTINCT(instance) FROM creature_respawn WHERE instance <> 0"); if( result ) { do @@ -295,7 +295,7 @@ void InstanceSaveManager::CleanupInstances() } // gameobject_respawn - result = WorldDatabase.PQuery("SELECT DISTINCT(instance) FROM gameobject_respawn WHERE instance <> 0"); + result = WorldDatabase.Query("SELECT DISTINCT(instance) FROM gameobject_respawn WHERE instance <> 0"); if( result ) { do @@ -324,7 +324,7 @@ void InstanceSaveManager::PackInstances() // all valid ids are in the instance table // any associations to ids not in this table are assumed to be // cleaned already in CleanupInstances - QueryResult *result = CharacterDatabase.PQuery("SELECT id FROM instance"); + QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance"); if( result ) { do @@ -374,7 +374,7 @@ void InstanceSaveManager::LoadResetTimes() // resettime = 0 in the DB for raid/heroic instances so those are skipped typedef std::map > ResetTimeMapType; ResetTimeMapType InstResetTime; - QueryResult *result = CharacterDatabase.PQuery("SELECT id, map, resettime FROM instance WHERE resettime > 0"); + QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0"); if( result ) { do @@ -390,7 +390,7 @@ void InstanceSaveManager::LoadResetTimes() delete result; // update reset time for normal instances with the max creature respawn time + X hours - result = WorldDatabase.PQuery("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); + result = WorldDatabase.Query("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); if( result ) { do diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 55f8f25ab..86ef6a110 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3399,7 +3399,7 @@ bool ChatHandler::HandleWpImportCommand(const char *args) { getline (infile,line); //cout << line << endl; - QueryResult *result = WorldDatabase.PQuery(line.c_str()); + QueryResult *result = WorldDatabase.Query(line.c_str()); delete result; } infile.close(); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 7fd5144f4..8a1117e03 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2630,7 +2630,7 @@ void ObjectMgr::LoadGroups() uint64 leaderGuid = 0; uint32 count = 0; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - QueryResult *result = CharacterDatabase.PQuery("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, leaderGuid FROM groups"); + QueryResult *result = CharacterDatabase.Query("SELECT mainTank, mainAssistant, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, leaderGuid FROM groups"); if( !result ) { @@ -2672,7 +2672,7 @@ void ObjectMgr::LoadGroups() group = NULL; leaderGuid = 0; // 0 1 2 3 - result = CharacterDatabase.PQuery("SELECT memberGuid, assistant, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid"); + result = CharacterDatabase.Query("SELECT memberGuid, assistant, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid"); if(!result) { barGoLink bar( 1 ); @@ -2725,7 +2725,7 @@ void ObjectMgr::LoadGroups() count = 0; group = NULL; leaderGuid = 0; - result = CharacterDatabase.PQuery( + result = CharacterDatabase.Query( // 0 1 2 3 4 5 "SELECT leaderGuid, map, instance, permanent, difficulty, resettime, " // 6 @@ -3593,7 +3593,7 @@ void ObjectMgr::LoadQuestLocales() void ObjectMgr::LoadPetCreateSpells() { - QueryResult *result = WorldDatabase.PQuery("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); + QueryResult *result = WorldDatabase.Query("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell"); if(!result) { barGoLink bar( 1 ); @@ -3973,7 +3973,7 @@ void ObjectMgr::LoadEventScripts() void ObjectMgr::LoadItemTexts() { - QueryResult *result = CharacterDatabase.PQuery("SELECT id, text FROM item_text"); + QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text"); uint32 count = 0; @@ -4056,7 +4056,7 @@ void ObjectMgr::LoadPageTextLocales() { mPageTextLocaleMap.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); + QueryResult *result = WorldDatabase.Query("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); if(!result) { @@ -5567,7 +5567,7 @@ void ObjectMgr::LoadCorpses() { uint32 count = 0; // 0 1 2 3 4 5 6 7 8 10 - QueryResult *result = CharacterDatabase.PQuery("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, guid FROM corpse WHERE corpse_type <> 0"); + QueryResult *result = CharacterDatabase.Query("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, guid FROM corpse WHERE corpse_type <> 0"); if( !result ) { @@ -5931,7 +5931,7 @@ void ObjectMgr::LoadReservedPlayersNames() { m_ReservedNames.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT name FROM reserved_name"); + QueryResult *result = WorldDatabase.Query("SELECT name FROM reserved_name"); uint32 count = 0; @@ -6771,7 +6771,7 @@ void ObjectMgr::LoadTrainerSpell() std::set skip_trainers; - QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); + QueryResult *result = WorldDatabase.Query("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); if( !result ) { @@ -6862,7 +6862,7 @@ void ObjectMgr::LoadVendors() std::set skip_vendors; - QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor"); + QueryResult *result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor"); if( !result ) { barGoLink bar( 1 ); @@ -6908,7 +6908,7 @@ void ObjectMgr::LoadNpcTextId() m_mCacheNpcTextIdMap.clear(); - QueryResult* result = WorldDatabase.PQuery("SELECT npc_guid, textid FROM npc_gossip"); + QueryResult* result = WorldDatabase.Query("SELECT npc_guid, textid FROM npc_gossip"); if( !result ) { barGoLink bar( 1 ); diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp index 5a1de100f..ccb35ef74 100644 --- a/src/game/SkillDiscovery.cpp +++ b/src/game/SkillDiscovery.cpp @@ -52,7 +52,7 @@ void LoadSkillDiscoveryTable() uint32 count = 0; // 0 1 2 - QueryResult *result = WorldDatabase.PQuery("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); + QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); if (result) { diff --git a/src/game/SkillExtraItems.cpp b/src/game/SkillExtraItems.cpp index c9d5f7e03..eebb443d4 100644 --- a/src/game/SkillExtraItems.cpp +++ b/src/game/SkillExtraItems.cpp @@ -57,7 +57,7 @@ void LoadSkillExtraItemTable() SkillExtraItemStore.clear(); // need for reload // 0 1 2 3 - QueryResult *result = WorldDatabase.PQuery("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template"); + QueryResult *result = WorldDatabase.Query("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template"); if (result) { diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index d89c6e301..c4202ca5b 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1458,7 +1458,7 @@ void SpellMgr::LoadSpellChains() mSpellChains.clear(); // need for reload case mSpellChainsNext.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain"); + QueryResult *result = WorldDatabase.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain"); if(result == NULL) { barGoLink bar( 1 ); @@ -1665,7 +1665,7 @@ void SpellMgr::LoadSpellLearnSpells() { mSpellLearnSpells.clear(); // need for reload case - QueryResult *result = WorldDatabase.PQuery("SELECT entry, SpellID FROM spell_learn_spell"); + QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID FROM spell_learn_spell"); if(!result) { barGoLink bar( 1 ); diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index a8a4abc0a..8bfd3c5f7 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -114,7 +114,7 @@ void MapManager::LoadTransports() sLog.outString( ">> Loaded %u transports", count ); // check transport data DB integrity - result = WorldDatabase.PQuery("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); + result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); if(result) // wrong data found { do From 322b201c4dd66f59ce5e86e003f4430a95f03aa6 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 23:28:32 +0100 Subject: [PATCH 14/18] Revert change from PQuery to Query for one accidentally included query. --- src/game/CharacterHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index ef4d358a4..700f4f858 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -309,7 +309,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) bool have_same_race = false; if(!AllowTwoSideAccounts || skipCinematics == 1) { - QueryResult *result2 = CharacterDatabase.Query("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); + QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); From ed7390dedefea31d480a4a842779390d15fa2c66 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 3 Nov 2008 01:09:18 +0300 Subject: [PATCH 15/18] Instead mark spell as delatable mark it as executed and referenced from Unit current spells array and not deleted spell in like cases. This is solve crashs if spell deleted at caster die in result triggered spells casting chain from currently executed spell. --- src/framework/Utilities/EventProcessor.cpp | 26 +++++++++++++++------- src/framework/Utilities/EventProcessor.h | 4 +++- src/game/Map.cpp | 3 +++ src/game/Spell.cpp | 18 ++++++++++++++- src/game/Spell.h | 9 +++++--- src/game/SpellAuras.cpp | 2 +- src/game/Unit.cpp | 24 +++++++++++--------- 7 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/framework/Utilities/EventProcessor.cpp b/src/framework/Utilities/EventProcessor.cpp index 65de7c1aa..2bcf6a46a 100644 --- a/src/framework/Utilities/EventProcessor.cpp +++ b/src/framework/Utilities/EventProcessor.cpp @@ -26,7 +26,7 @@ EventProcessor::EventProcessor() EventProcessor::~EventProcessor() { - KillAllEvents(); + KillAllEvents(true); } void EventProcessor::Update(uint32 p_time) @@ -58,21 +58,31 @@ void EventProcessor::Update(uint32 p_time) } } -void EventProcessor::KillAllEvents() +void EventProcessor::KillAllEvents(bool force) { // prevent event insertions m_aborting = true; // first, abort all existing events - for (EventList::iterator i = m_events.begin(); i != m_events.end(); ++i) + for (EventList::iterator i = m_events.begin(); i != m_events.end();) { - i->second->to_Abort = true; - i->second->Abort(m_time); - delete i->second; + EventList::iterator i_old = i; + ++i; + + i_old->second->to_Abort = true; + i_old->second->Abort(m_time); + if(force || i_old->second->IsDeletable()) + { + delete i_old->second; + + if(!force) // need per-element cleanup + m_events.erase (i_old); + } } - // clear event list - m_events.clear(); + // fast clear event list (in force case) + if(force) + m_events.clear(); } void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) diff --git a/src/framework/Utilities/EventProcessor.h b/src/framework/Utilities/EventProcessor.h index 5d83c02a2..350db5bb5 100644 --- a/src/framework/Utilities/EventProcessor.h +++ b/src/framework/Utilities/EventProcessor.h @@ -38,6 +38,8 @@ class BasicEvent // e_time is execution time, p_time is update interval virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } + virtual bool IsDeletable() const { return true; } // this event can be safely deleted + virtual void Abort(uint64 /*e_time*/) {} // this method executes when the event is aborted bool to_Abort; // set by externals when the event is aborted, aborted events don't execute @@ -57,7 +59,7 @@ class EventProcessor ~EventProcessor(); void Update(uint32 p_time); - void KillAllEvents(); + void KillAllEvents(bool force); void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); uint64 CalculateTime(uint64 t_offset); protected: diff --git a/src/game/Map.cpp b/src/game/Map.cpp index fad5200f2..7518cf170 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1355,6 +1355,9 @@ void Map::RemoveAllObjectsInRemoveList() Remove((GameObject*)obj,true); break; case TYPEID_UNIT: + // in case triggred sequence some spell can continue casting after prev CleanupsBeforeDelete call + // make sure that like sources auras/etc removed before destructor start + ((Creature*)obj)->CleanupsBeforeDelete (); Remove((Creature*)obj,true); break; default: diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 982d5b02a..a18a8cd3a 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -268,7 +268,8 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_caster = Caster; m_selfContainer = NULL; m_triggeringContainer = triggeringContainer; - m_deletable = true; + m_referencedFromCurrentSpell = false; + m_executedCurrently = false; m_delayAtDamageCount = 0; m_applyMultiplierMask = 0; @@ -2019,6 +2020,8 @@ void Spell::cancel() void Spell::cast(bool skipCheck) { + SetExecutedCurrently(true); + uint8 castResult = 0; // update pointers base at GUIDs to prevent access to non-existed already object @@ -2028,6 +2031,7 @@ void Spell::cast(bool skipCheck) if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID()) { cancel(); + SetExecutedCurrently(false); return; } @@ -2039,6 +2043,7 @@ void Spell::cast(bool skipCheck) { SendCastResult(castResult); finish(false); + SetExecutedCurrently(false); return; } @@ -2050,6 +2055,7 @@ void Spell::cast(bool skipCheck) { SendCastResult(castResult); finish(false); + SetExecutedCurrently(false); return; } } @@ -2082,7 +2088,10 @@ void Spell::cast(bool skipCheck) FillTargetMap(); if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap + { + SetExecutedCurrently(false); return; + } SendCastResult(castResult); SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()... @@ -2114,6 +2123,8 @@ void Spell::cast(bool skipCheck) // Immediate spell, no big deal handle_immediate(); } + + SetExecutedCurrently(false); } void Spell::handle_immediate() @@ -5063,3 +5074,8 @@ void SpellEvent::Abort(uint64 /*e_time*/) if (m_Spell->getState() != SPELL_STATE_FINISHED) m_Spell->cancel(); } + +bool SpellEvent::IsDeletable() const +{ + return m_Spell->IsDeletable(); +} diff --git a/src/game/Spell.h b/src/game/Spell.h index 093a91570..aa32c326a 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -380,8 +380,9 @@ class Spell bool IsMeleeAttackResetSpell() const { return !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } bool IsRangedAttackResetSpell() const { return !m_IsTriggeredSpell && IsRangedSpell() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } - bool IsDeletable() const { return m_deletable; } - void SetDeletable(bool deletable) { m_deletable = deletable; } + bool IsDeletable() const { return !m_referencedFromCurrentSpell && !m_executedCurrently; } + void SetReferencedFromCurrent(bool yes) { m_referencedFromCurrentSpell = yes; } + void SetExecutedCurrently(bool yes) { m_executedCurrently = yes; } uint64 GetDelayStart() const { return m_delayStart; } void SetDelayStart(uint64 m_time) { m_delayStart = m_time; } uint64 GetDelayMoment() const { return m_delayMoment; } @@ -433,7 +434,8 @@ class Spell bool m_immediateHandled; // were immediate actions handled? (used by delayed spells only) // These vars are used in both delayed spell system and modified immediate spell system - bool m_deletable; // is the spell pending deletion or must be updated till permitted to delete? + bool m_referencedFromCurrentSpell; // mark as references to prevent deleted and access by dead pointers + bool m_executedCurrently; // mark as executed to prevent deleted and access by dead pointers bool m_needSpellLog; // need to send spell log? uint8 m_applyMultiplierMask; // by effect: damage multiplier needed? float m_damageMultipliers[3]; // by effect: damage multiplier @@ -695,6 +697,7 @@ class SpellEvent : public BasicEvent virtual bool Execute(uint64 e_time, uint32 p_time); virtual void Abort(uint64 e_time); + virtual bool IsDeletable() const; protected: Spell* m_Spell; }; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 2f29cfc46..31354130f 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3470,7 +3470,7 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING ) { currentSpell->cancel(); - currentSpell->SetDeletable(true); + currentSpell->SetReferencedFromCurrent(false); m_target->m_currentSpells[i] = NULL; } } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7e68980b9..46f5a15aa 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -233,9 +233,11 @@ Unit::~Unit() // set current spells as deletable for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) { - // spell may be safely deleted now - if (m_currentSpells[i]) m_currentSpells[i]->SetDeletable(true); - m_currentSpells[i] = NULL; + if (m_currentSpells[i]) + { + m_currentSpells[i]->SetReferencedFromCurrent(false); + m_currentSpells[i] = NULL; + } } RemoveAllGameObjects(); @@ -3145,7 +3147,7 @@ void Unit::_UpdateSpells( uint32 time ) { if (m_currentSpells[i] && m_currentSpells[i]->getState() == SPELL_STATE_FINISHED) { - m_currentSpells[i]->SetDeletable(true); // spell may be safely deleted now + m_currentSpells[i]->SetReferencedFromCurrent(false); m_currentSpells[i] = NULL; // remove pointer } } @@ -3258,7 +3260,6 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) uint32 CSpellType = pSpell->GetCurrentContainer(); - pSpell->SetDeletable(false); // spell will not be deleted until gone from current pointers if (pSpell == m_currentSpells[CSpellType]) return; // avoid breaking self // break same type spell if it is not delayed @@ -3315,10 +3316,11 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) // current spell (if it is still here) may be safely deleted now if (m_currentSpells[CSpellType]) - m_currentSpells[CSpellType]->SetDeletable(true); + m_currentSpells[CSpellType]->SetReferencedFromCurrent(false); // set new current spell m_currentSpells[CSpellType] = pSpell; + pSpell->SetReferencedFromCurrent(true); } void Unit::InterruptSpell(uint32 spellType, bool withDelayed) @@ -3336,7 +3338,7 @@ void Unit::InterruptSpell(uint32 spellType, bool withDelayed) if (m_currentSpells[spellType]->getState() != SPELL_STATE_FINISHED) m_currentSpells[spellType]->cancel(); - m_currentSpells[spellType]->SetDeletable(true); + m_currentSpells[spellType]->SetReferencedFromCurrent(false); m_currentSpells[spellType] = NULL; } } @@ -3372,7 +3374,7 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) if ( (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) && (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) ) m_currentSpells[CURRENT_GENERIC_SPELL]->cancel(); - m_currentSpells[CURRENT_GENERIC_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_GENERIC_SPELL]->SetReferencedFromCurrent(false); m_currentSpells[CURRENT_GENERIC_SPELL] = NULL; } @@ -3386,7 +3388,7 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) if ( (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_FINISHED) && (withDelayed || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_DELAYED) ) m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->cancel(); - m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->SetReferencedFromCurrent(false); m_currentSpells[CURRENT_AUTOREPEAT_SPELL] = NULL; } @@ -3395,7 +3397,7 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) { if (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel(); - m_currentSpells[CURRENT_CHANNELED_SPELL]->SetDeletable(true); + m_currentSpells[CURRENT_CHANNELED_SPELL]->SetReferencedFromCurrent(false); m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL; } } @@ -9791,7 +9793,7 @@ void Unit::CleanupsBeforeDelete() if(m_uint32Values) // only for fully created object { InterruptNonMeleeSpells(true); - m_Events.KillAllEvents(); + m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted ans will deleated at call in Map::RemoveAllObjectsInRemoveList CombatStop(); ClearComboPointHolders(); DeleteThreatList(); From 166007525ec1033157d77a84d37518c11f2256d1 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 3 Nov 2008 01:45:54 +0300 Subject: [PATCH 16/18] More fixes for wrong format arg/value pairs. --- src/game/Level2.cpp | 2 +- src/game/Object.h | 5 ++--- src/game/ObjectMgr.cpp | 12 ++++++++---- src/game/Pet.cpp | 3 ++- src/game/PetitionsHandler.cpp | 5 +++-- src/game/Player.cpp | 14 +++++--------- src/game/QueryHandler.cpp | 6 ++++-- src/game/QuestHandler.cpp | 5 +++-- src/game/SpellAuras.cpp | 4 ++-- src/game/SpellEffects.cpp | 15 ++++++++++----- src/game/SpellHandler.cpp | 2 +- src/game/Transports.cpp | 3 ++- src/game/WaypointManager.cpp | 8 ++++++-- src/game/World.cpp | 6 ++++-- 14 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 86ef6a110..9a4d6a138 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -1800,7 +1800,7 @@ bool ChatHandler::HandlePInfoCommand(const char* args) else { // 0 - QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", targetGUID); + QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID)); if (!result) { SendSysMessage(LANG_PLAYER_NOT_FOUND); diff --git a/src/game/Object.h b/src/game/Object.h index 127205401..0d0ecc7d0 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -30,9 +30,8 @@ #include #define CONTACT_DISTANCE 0.5f -#define INTERACTION_DISTANCE 5 -#define ATTACK_DISTANCE 5 -#define DETECT_DISTANCE 20 // max distance to successful detect stealthed unit +#define INTERACTION_DISTANCE 5.0f +#define ATTACK_DISTANCE 5.0f #define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2.0f) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells) #define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 8a1117e03..724880f5d 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3802,19 +3802,22 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) if(float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) { - sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u",tablename,tmp.datalong2,tmp.id); + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u", + tablename,tmp.datalong2,tmp.id); continue; } if(tmp.datalong2 && float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) { - sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %u or 0 for disable distance check",tablename,tmp.datalong2,tmp.id,uint32(DEFAULT_VISIBILITY_DISTANCE)); + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %f or 0 for disable distance check", + tablename,tmp.datalong2,tmp.id,DEFAULT_VISIBILITY_DISTANCE); continue; } if(tmp.datalong2 && float(tmp.datalong2) < INTERACTION_DISTANCE) { - sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %u or 0 for disable distance check",tablename,tmp.datalong2,tmp.id,uint32(INTERACTION_DISTANCE)); + sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %f or 0 for disable distance check", + tablename,tmp.datalong2,tmp.id,INTERACTION_DISTANCE); continue; } @@ -3826,7 +3829,8 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) { if(!sSpellStore.LookupEntry(tmp.datalong)) { - sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u",tablename,tmp.datalong,tmp.id); + sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u", + tablename,tmp.datalong,tmp.id); continue; } break; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index ae190fb4d..7c40ff32a 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -932,7 +932,8 @@ bool Pet::CreateBaseAtCreature(Creature* creature) if(!IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); return false; } diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index d53e7ab24..1064bd23f 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -833,8 +833,9 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) for(uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); - sLog.outDebug("PetitionsHandler: adding arena member %u", fields[0].GetUInt64()); - at->AddMember(fields[0].GetUInt64()); + uint64 memberGUID = fields[0].GetUInt64(); + sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID)); + at->AddMember(memberGUID); result->NextRow(); } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 74a71742c..df3d925d0 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3946,24 +3946,20 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g uint32 LostDurability = maxDurability - curDurability; if(LostDurability>0) { - ItemPrototype const *ditemProto = sItemStorage.LookupEntry(item->GetEntry()); - if(!ditemProto) - { - sLog.outError("ERROR: RepairDurability: Unknown item id %u", ditemProto); - return TotalCost; - } + ItemPrototype const *ditemProto = item->GetProto(); DurabilityCostsEntry const *dcost = sDurabilityCostsStore.LookupEntry(ditemProto->ItemLevel); if(!dcost) { - sLog.outError("ERROR: RepairDurability: Wrong item lvl %u", dcost); + sLog.outError("ERROR: RepairDurability: Wrong item lvl %u", ditemProto->ItemLevel); return TotalCost; } - DurabilityQualityEntry const *dQualitymodEntry = sDurabilityQualityStore.LookupEntry((ditemProto->Quality+1)*2); + uint32 dQualitymodEntryId = (ditemProto->Quality+1)*2; + DurabilityQualityEntry const *dQualitymodEntry = sDurabilityQualityStore.LookupEntry(dQualitymodEntryId); if(!dQualitymodEntry) { - sLog.outError("ERROR: RepairDurability: Wrong dQualityModEntry %u", dQualitymodEntry); + sLog.outError("ERROR: RepairDurability: Wrong dQualityModEntry %u", dQualitymodEntryId); return TotalCost; } diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 0c3ad1f04..2c912a9e7 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -200,7 +200,8 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: CMSG_CREATURE_QUERY - (%u) NO CREATURE INFO! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry ); + sLog.outDebug("WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)", + GUID_LOPART(guid), entry); WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 4 ); data << uint32(entry | 0x80000000); SendPacket( &data ); @@ -259,7 +260,8 @@ void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - (%u) Missing gameobject info for (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entryID ); + sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", + GUID_LOPART(guid), entryID ); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 ); data << uint32(entryID | 0x80000000); SendPacket( &data ); diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 0334332a9..5b68829ab 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -85,12 +85,13 @@ void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u",guid ); + sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_NONE); if (!pCreature) { - sLog.outDebug( "WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", + GUID_LOPART(guid)); return; } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 31354130f..0beaf61a8 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -5622,7 +5622,7 @@ void Aura::PeriodicTick() pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size data.append(m_target->GetPackGUID()); @@ -5743,7 +5743,7 @@ void Aura::PeriodicTick() pdamage = uint32(m_target->GetHealth()); sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GetCasterGUID(), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5077d87e7..0e08b9c18 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1870,7 +1870,8 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx) if(!spellInfo) { - sLog.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id); + sLog.outError("EffectTriggerMissileSpell of spell %u (eff: %u): triggering unknown spell id %u", + m_spellInfo->Id,effect_idx,triggered_spell_id); return; } @@ -3184,7 +3185,8 @@ void Spell::EffectSummon(uint32 i) if(!spawnCreature->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", + spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); delete spawnCreature; return; } @@ -3614,7 +3616,8 @@ void Spell::EffectSummonGuardian(uint32 i) if(!spawnCreature->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", + spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY()); delete spawnCreature; return; } @@ -4009,7 +4012,8 @@ void Spell::EffectSummonPet(uint32 i) if(!NewSummon->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", + NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY()); delete NewSummon; return; } @@ -5603,7 +5607,8 @@ void Spell::EffectSummonCritter(uint32 i) if(!critter->IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", + critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); delete critter; return; } diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 7d43e794b..3f4a6a846 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -267,7 +267,7 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) recv_data >> guid; - sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", guid); + sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid); if(!obj) diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 8bfd3c5f7..2cdf080f7 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -146,7 +146,8 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, if(!IsPositionValid()) { - sLog.outError("ERROR: Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",guidlow,x,y); + sLog.outError("ERROR: Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow,x,y); return false; } diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index f157234fa..b123fe497 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -89,8 +89,12 @@ void WaypointManager::Load() if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation)) { QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id); - if(result1) sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y); - else sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %d, Y: %d).", id, point, node.x, node.y); + if(result1) + sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %f, Y: %f).", + id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y); + else + sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %f, Y: %f).", + id, point, node.x, node.y); MaNGOS::NormalizeMapCoord(node.x); MaNGOS::NormalizeMapCoord(node.y); diff --git a/src/game/World.cpp b/src/game/World.cpp index a8bc9a669..4f9dcb005 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -480,7 +480,8 @@ void World::LoadConfigSettings(bool reload) } else if(rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > ATTACK_DISTANCE) { - sLog.outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.",rate_values[RATE_TARGET_POS_RECALCULATION_RANGE],ATTACK_DISTANCE,ATTACK_DISTANCE); + sLog.outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.", + rate_values[RATE_TARGET_POS_RECALCULATION_RANGE],ATTACK_DISTANCE,ATTACK_DISTANCE); rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = ATTACK_DISTANCE; } @@ -1153,7 +1154,8 @@ void World::SetInitialWorldSettings() sprintf( isoDate, "%04d-%02d-%02d %02d:%02d:%02d", local.tm_year+1900, local.tm_mon+1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); - WorldDatabase.PExecute("INSERT INTO uptime (startstring, starttime, uptime) VALUES('%s', %ld, 0)", isoDate, m_startTime ); + WorldDatabase.PExecute("INSERT INTO uptime (startstring, starttime, uptime) VALUES('%s', " I64FMTD ", 0)", + isoDate, uint64(m_startTime)); m_timers[WUPDATE_OBJECTS].SetInterval(0); m_timers[WUPDATE_SESSIONS].SetInterval(0); From 2cdd7dcfce3cc42c05dc349551e70caccf583d33 Mon Sep 17 00:00:00 2001 From: hunuza Date: Mon, 3 Nov 2008 10:58:29 +0100 Subject: [PATCH 17/18] Improve some arena team related DB access. Reduce number of queries for adding a new arena team member. Merge two queries in Player::GetArenaTeamIdFromDB() into one. --- src/game/ArenaTeam.cpp | 53 +++++++++++++++++++++++------------------- src/game/Player.cpp | 31 ++++-------------------- 2 files changed, 34 insertions(+), 50 deletions(-) diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 36ae28165..b8796f61a 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -88,40 +88,45 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid) std::string plName; uint8 plClass; + // arena team is full (can't have more than type * 2 players!) if(GetMembersSize() >= GetType() * 2) - { - // arena team is full (can't have more than type * 2 players!) - // return false return false; - } - if(!objmgr.GetPlayerNameByGUID(PlayerGuid, plName)) // player doesnt exist - return false; - // player already in arenateam of that size - if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0) + Player *pl = objmgr.GetPlayer(PlayerGuid); + if(pl) { - sLog.outError("Arena::AddMember() : player already in this sized team"); - return false; + if(pl->GetArenaTeamId(GetType())) + { + sLog.outError("Arena::AddMember() : player already in this sized team"); + return false; + } + + plClass = (uint8)pl->getClass(); + plName = pl->GetName(); + } + else + { + // 0 1 + QueryResult *result = CharacterDatabase.PQuery("SELECT name, class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid)); + if(!result) + return false; + + plName = (*result)[0].GetCppString(); + plClass = (*result)[1].GetUInt8(); + delete result; + + // check if player already in arenateam of that size + if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0) + { + sLog.outError("Arena::AddMember() : player already in this sized team"); + return false; + } } // remove all player signs from another petitions // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(PlayerGuid, GetType()); - Player *pl = objmgr.GetPlayer(PlayerGuid); - if(pl) - { - plClass = (uint8)pl->getClass(); - } - else - { - QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid)); - if(!result) - return false; - plClass = (*result)[0].GetUInt8(); - delete result; - } - ArenaTeamMember newmember; newmember.name = plName; newmember.guid = PlayerGuid; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index df3d925d0..55c4b7bee 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6012,32 +6012,11 @@ uint32 Player::GetRankFromDB(uint64 guid) uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) { - // need fix it! - QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid FROM arena_team_member WHERE guid='%u'", GUID_LOPART(guid)); - if(result) - { - // init id to 0, check the arena type before assigning a value to id - uint32 id = 0; - do - { - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM arena_team WHERE arenateamid='%u'", id); - if(result2) - { - uint8 dbtype = (*result2)[0].GetUInt32(); - delete result2; - if(dbtype == type) - { - // if the type matches, we've found the id - id = (*result)[0].GetUInt32(); - break; - } - } - } while(result->NextRow()); - delete result; - return id; - } - // no arenateam for the specified guid, return 0 - return 0; + QueryResult *result = CharacterDatabase.PQuery("SELECT arena_team_member.arenateamid FROM arena_team_member JOIN arena_team ON arena_team_member.arenateamid = arena_team.arenateamid WHERE guid='%u' AND type='%u' LIMIT 1", GUID_LOPART(guid), type); + if(!result) + return 0; + + return (*result)[0].GetUInt32(); } uint32 Player::GetZoneIdFromDB(uint64 guid) From 2c9eae759902ac01b3c03b5e4220cf3043313c77 Mon Sep 17 00:00:00 2001 From: hunuza Date: Mon, 3 Nov 2008 11:11:27 +0100 Subject: [PATCH 18/18] Fixed memory leak by adding missing delete of query result. --- src/game/Player.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 55c4b7bee..4b318d44d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6016,7 +6016,9 @@ uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) if(!result) return 0; - return (*result)[0].GetUInt32(); + uint32 id = (*result)[0].GetUInt32(); + delete result; + return id; } uint32 Player::GetZoneIdFromDB(uint64 guid)