diff options
author | Shauren <none@none> | 2010-10-09 17:36:53 +0200 |
---|---|---|
committer | Shauren <none@none> | 2010-10-09 17:36:53 +0200 |
commit | 324de6fb4c6f56ac08a487d24e47e457bf11b5c3 (patch) | |
tree | f73297b924190f1b95a8905ec3ba3efa569d6f30 /src | |
parent | a20dd32de0a0eaea8a7e869b0b0aedf3f6920b5a (diff) |
Core: Added some anti-WPE filter checks to prevent putting non-empty bags into other bags/gbank/mail/auction, original patch from mythcore
Core: Changed inventory saving - will no longer abort operation at single item fail
Closes issue #1994.
--HG--
branch : trunk
Diffstat (limited to 'src')
4 files changed, 61 insertions, 32 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2dfccde8017..5926589ef76 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -10039,6 +10039,9 @@ uint8 Player::_CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVe uint32 need_space; + if (pSrcItem && pSrcItem->IsBag() && !((Bag*)pSrcItem)->IsEmpty() && !IsBagPos(uint16(bag) << 8 | slot)) + return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS; + // empty specific slot - check item fit to slot if (!pItem2 || swap) { @@ -10111,6 +10114,9 @@ uint8 Player::_CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, ItemPrototyp if (!pBag || pBag == pSrcItem) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + if (pSrcItem && pSrcItem->IsBag() && !((Bag*)pSrcItem)->IsEmpty()) + return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS; + ItemPrototype const* pBagProto = pBag->GetProto(); if (!pBagProto) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; @@ -10169,6 +10175,10 @@ uint8 Player::_CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, ItemPrototyp uint8 Player::_CanStoreItem_InInventorySlots(uint8 slot_begin, uint8 slot_end, ItemPosCountVec &dest, ItemPrototype const *pProto, uint32& count, bool merge, Item* pSrcItem, uint8 skip_bag, uint8 skip_slot) const { + //this is never called for non-bag slots so we can do this + if (pSrcItem && pSrcItem->IsBag() && !((Bag*)pSrcItem)->IsEmpty()) + return EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS; + for (uint32 j = slot_begin; j < slot_end; j++) { // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot @@ -18056,52 +18066,52 @@ void Player::_SaveInventory(SQLTransaction& trans) if (m_itemUpdateQueue.empty()) return; - // do not save if the update queue is corrupt - bool error = false; + uint32 lowGuid = GetGUIDLow(); for (size_t i = 0; i < m_itemUpdateQueue.size(); ++i) { Item *item = m_itemUpdateQueue[i]; - if (!item || item->GetState() == ITEM_REMOVED) + if (!item) continue; - Item *test = GetItemByPos(item->GetBagSlot(), item->GetSlot()); - - if (test == NULL) - { - sLog.outCrash("Player(GUID: %u Name: %s)::_SaveInventory - the bag(%d) and slot(%d) values for the item with guid %d (state %d) are incorrect, the player doesn't have an item at that position!", GetGUIDLow(), GetName(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), (int32)item->GetState()); - //error = true; - //Should the above line really be commented out? - } - else if (test != item) - { - sLog.outError("Player(GUID: %u Name: %s)::_SaveInventory - the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the item with guid %d is there instead!", GetGUIDLow(), GetName(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); - error = true; - } - } - - if (error) - { - sLog.outError("Player::_SaveInventory - one or more errors occurred save aborted!"); - ChatHandler(this).SendSysMessage(LANG_ITEM_SAVE_FAILED); - return; - } - - for (size_t i = 0; i < m_itemUpdateQueue.size(); i++) - { - Item *item = m_itemUpdateQueue[i]; - if (!item) continue; - Bag *container = item->GetContainer(); uint32 bag_guid = container ? container->GetGUIDLow() : 0; + if (item->GetState() != ITEM_REMOVED) + { + Item *test = GetItemByPos(item->GetBagSlot(), item->GetSlot()); + if (test == NULL) + { + uint32 bagTestGUID = 0; + if (Item* test2 = GetItemByPos(INVENTORY_SLOT_BAG_0, item->GetBagSlot())) + bagTestGUID = test2->GetGUIDLow(); + sLog.outError("Player(GUID: %u Name: %s)::_SaveInventory - the bag(%u) and slot(%u) values for the item with guid %u (state %d) are incorrect, the player doesn't have an item at that position!", lowGuid, GetName(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), (int32)item->GetState()); + // according to the test that was just performed nothing should be in this slot, delete + trans->PAppend("DELETE FROM character_inventory WHERE bag=%u AND slot=%u", bagTestGUID, item->GetSlot()); + // also THIS item should be somewhere else, cheat attempt + item->FSetState(ITEM_REMOVED); // we are IN updateQueue right now, can't use SetState which modifies the queue + DeleteRefundReference(item->GetGUIDLow()); + // don't skip, let the switch delete it + //continue; + } + else if (test != item) + { + sLog.outError("Player(GUID: %u Name: %s)::_SaveInventory - the bag(%u) and slot(%u) values for the item with guid %u are incorrect, the item with guid %u is there instead!", lowGuid, GetName(), item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); + // save all changes to the item... + if (item->GetState() != ITEM_NEW) // only for existing items, no dupes + item->SaveToDB(trans); + // ...but do not save position in invntory + continue; + } + } + switch (item->GetState()) { case ITEM_NEW: - trans->PAppend("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); + trans->PAppend("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", lowGuid, bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); break; case ITEM_CHANGED: trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); - trans->PAppend("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); + trans->PAppend("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", lowGuid, bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); break; case ITEM_REMOVED: trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index eab64fd0731..3ed1a6a9d7a 100755 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1977,6 +1977,13 @@ void Guild::MoveFromCharToBank(Player * pl, uint8 PlayerBag, uint8 PlayerSlot, u if (!pItemChar) // Problem to get item from player return; + // prevent storing non-empty bags + if (pItemChar && pItemChar->IsBag() && !((Bag*)pItemChar)->IsEmpty()) + { + pl->SendEquipError(EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS, pItemChar, NULL); + return; + } + if (!pItemChar->CanBeTraded()) { pl->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL); diff --git a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp index 677e879a8f2..3fbfbfe6980 100755 --- a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp @@ -192,6 +192,12 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) return; } + if (it->IsBag() && !((Bag*)it)->IsEmpty()) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(pCreature->getFaction()); //we have to take deposit : diff --git a/src/server/game/Server/Protocol/Handlers/MailHandler.cpp b/src/server/game/Server/Protocol/Handlers/MailHandler.cpp index dbc4134d90f..f1ffd691b22 100755 --- a/src/server/game/Server/Protocol/Handlers/MailHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/MailHandler.cpp @@ -219,6 +219,12 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) return; } + if (item->IsBag() && !((Bag*)item)->IsEmpty()) + { + pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS); + return; + } + items[i] = item; } |