Fix vector crash stack trace

This commit is contained in:
Taurus
2025-09-24 17:28:26 +08:00
committed by GitHub
parent 1efc29f093
commit 19f8fd76af

View File

@@ -16,87 +16,189 @@
*/
#include "aoe_loot.h"
#include <limits>
#include <algorithm>
void AOELootPlayer::OnPlayerLogin(Player* player)
{
if (!player)
return;
if (sConfigMgr->GetOption<bool>("AOELoot.Enable", true))
{
if (sConfigMgr->GetOption<bool>("AOELoot.Message", true))
ChatHandler(player->GetSession()).PSendSysMessage(AOE_ACORE_STRING_MESSAGE);
{
if (WorldSession* session = player->GetSession())
{
ChatHandler(session).PSendSysMessage(AOE_ACORE_STRING_MESSAGE);
}
}
}
}
bool AOELootServer::CanPacketReceive(WorldSession* session, WorldPacket& packet)
{
if (packet.GetOpcode() == CMSG_LOOT)
{
Player* player = session->GetPlayer();
// Only handle loot packets
if (packet.GetOpcode() != CMSG_LOOT)
return true;
if (!sConfigMgr->GetOption<bool>("AOELoot.Enable", true))
return true;
// Basic validation checks
if (!session)
return true;
if (player->GetGroup() && !sConfigMgr->GetOption<bool>("AOELoot.Group", true))
return true;
Player* player = session->GetPlayer();
if (!player)
return true;
float range = sConfigMgr->GetOption<float>("AOELoot.Range", 55.0);
// Check if module is enabled
if (!sConfigMgr->GetOption<bool>("AOELoot.Enable", true))
return true;
std::list<Creature*> lootcreature; player->GetDeadCreatureListInGrid(lootcreature, range);
// Check group settings
if (player->GetGroup() && !sConfigMgr->GetOption<bool>("AOELoot.Group", true))
return true;
ObjectGuid guid; packet >> guid;
// Get configured loot range
float range = sConfigMgr->GetOption<float>("AOELoot.Range", 30.0f);
Loot* mainloot = &(player->GetMap()->GetCreature(guid))->loot;
// Limit range to reasonable values
if (range < 5.0f)
range = 5.0f;
if (range > 100.0f)
range = 100.0f;
for (auto itr = lootcreature.begin(); itr != lootcreature.end(); ++itr)
// Read target GUID from packet
ObjectGuid targetGuid;
packet >> targetGuid;
if (!targetGuid)
return true;
// Get target creature
Creature* mainCreature = player->GetMap()->GetCreature(targetGuid);
if (!mainCreature)
return true;
// Check if main creature has loot
if (!mainCreature->HasDynamicFlag(UNIT_DYNFLAG_LOOTABLE))
return true;
// Get nearby corpses
std::list<Creature*> nearbyCorpses;
player->GetDeadCreatureListInGrid(nearbyCorpses, range);
// Remove invalid corpses and main target
nearbyCorpses.remove_if([&](Creature* c)
{
Creature* creature = *itr;
return !c ||
c->GetGUID() == targetGuid ||
!c->HasDynamicFlag(UNIT_DYNFLAG_LOOTABLE) ||
!player->isAllowedToLoot(c);
});
// Prevent infiny add items
if (creature->GetGUID() == guid)
continue;
// Prevent steal loot
if (!player->GetMap()->Instanceable())
if (!player->isAllowedToLoot(creature))
continue;
// Max 15 items per creature
if (mainloot->items.size() + mainloot->quest_items.size() > 15)
break;
Loot* loot = &(*itr)->loot;
// FILL QITEMS
if (!loot->quest_items.empty())
{
mainloot->items.insert(mainloot->items.end(), loot->quest_items.begin(), loot->quest_items.end());
loot->quest_items.clear();
}
// FILL GOLD
if (loot->gold != 0)
{
mainloot->gold += loot->gold;
loot->gold = 0;
}
// FILL ITEMS
if (!loot->items.empty())
{
mainloot->items.insert(mainloot->items.end(), loot->items.begin(), loot->items.end());
loot->items.clear();
}
// Set flag for skinning
if (loot->items.empty() && loot->quest_items.empty())
{
creature->AllLootRemovedFromCorpse();
creature->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
}
}
player->SendLoot(guid, LOOT_CORPSE);
// If no other corpses, process normally
if (nearbyCorpses.empty())
{
player->SendLoot(targetGuid, LOOT_CORPSE);
return false;
}
return true;
// Get main loot
Loot* mainLoot = &mainCreature->loot;
// Limit number of corpses to process
const size_t maxCorpses = 10; // 减少到10个以提高稳定性
size_t processedCorpses = 0;
// Track total gold to merge
uint32 totalGold = mainLoot->gold;
// Collect all items to merge (don't modify main loot directly)
std::vector<LootItem> itemsToAdd;
std::vector<LootItem> questItemsToAdd;
for (Creature* creature : nearbyCorpses)
{
if (processedCorpses >= maxCorpses)
break;
if (!creature)
continue;
Loot* loot = &creature->loot;
// Skip already looted corpses
if (loot->isLooted())
continue;
// Collect gold
if (loot->gold > 0)
{
// Prevent overflow
if (totalGold < std::numeric_limits<uint32>::max() - loot->gold)
{
totalGold += loot->gold;
}
}
// Collect regular items
for (size_t i = 0; i < loot->items.size(); ++i)
{
// Check if there's still space
if (mainLoot->items.size() + itemsToAdd.size() +
mainLoot->quest_items.size() + questItemsToAdd.size() >= 15)
{
break;
}
itemsToAdd.push_back(loot->items[i]);
}
// Collect quest items
for (size_t i = 0; i < loot->quest_items.size(); ++i)
{
// Check if there's still space
if (mainLoot->items.size() + itemsToAdd.size() +
mainLoot->quest_items.size() + questItemsToAdd.size() >= 15)
{
break;
}
questItemsToAdd.push_back(loot->quest_items[i]);
}
// Clear source loot (but don't modify vector directly)
loot->clear();
creature->AllLootRemovedFromCorpse();
creature->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
processedCorpses++;
}
// Now safely add collected items to main loot
// Update gold
mainLoot->gold = totalGold;
// Add regular items
for (const auto& item : itemsToAdd)
{
if (mainLoot->items.size() < 15)
{
mainLoot->items.push_back(item);
}
}
// Add quest items
for (const auto& item : questItemsToAdd)
{
if (mainLoot->quest_items.size() < 15)
{
mainLoot->quest_items.push_back(item);
}
}
// Send merged loot window
player->SendLoot(targetGuid, LOOT_CORPSE);
return false;
}