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
This commit is contained in:
1 parent
a20dd32de0
commit
324de6fb4c
4 files changed
+61
-32
No files matched your search
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 :
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user