ZoneServer::KillSpawnByDistance deadlock fixed by calling outside of grid mutex lock. Killing spawn resulted in dropping loot chest, then Entity::DropChest calls SetLocation which calls AddSpawnToGrid causing deadlock.
This commit is contained in:
parent
1bc87d6617
commit
3045b15f88
@ -4653,36 +4653,15 @@ void ZoneServer::KillSpawnByDistance(Spawn* spawn, float max_distance, bool incl
|
||||
if(!spawn)
|
||||
return;
|
||||
|
||||
auto loc = glm::vec3(spawn->GetX(), spawn->GetZ(), spawn->GetY());
|
||||
std::vector<int32> grids_by_radius;
|
||||
if(spawn->GetMap()) {
|
||||
grids_by_radius = GetGridsByLocation(spawn, loc, max_distance);
|
||||
}
|
||||
else {
|
||||
grids_by_radius.push_back(spawn->GetLocation());
|
||||
}
|
||||
|
||||
Spawn* test_spawn = 0;
|
||||
MGridMaps.lock_shared();
|
||||
std::vector<int32>::iterator grid_radius_itr;
|
||||
for(grid_radius_itr = grids_by_radius.begin(); grid_radius_itr != grids_by_radius.end(); grid_radius_itr++) {
|
||||
std::map<int32, GridMap*>::iterator grids = grid_maps.find((*grid_radius_itr));
|
||||
if(grids != grid_maps.end()) {
|
||||
grids->second->MSpawns.lock_shared();
|
||||
typedef map <int32, Spawn*> SpawnMapType;
|
||||
for( SpawnMapType::iterator it = grids->second->spawns.begin(); it != grids->second->spawns.end(); ++it ) {
|
||||
test_spawn = it->second;
|
||||
if(test_spawn && test_spawn->Alive() && test_spawn->GetID() > 0 && test_spawn->GetID() != spawn->GetID() && test_spawn->IsEntity() &&
|
||||
(!test_spawn->IsPlayer() || include_players)){
|
||||
if(test_spawn->GetDistance(spawn) < max_distance)
|
||||
std::vector<std::pair<int32, float>> spawns = GetSpawnsByDistance(spawn, max_distance, include_players);
|
||||
for (const auto& pair : spawns) {
|
||||
int32 target_id = pair.first;
|
||||
Spawn* test_spawn = GetSpawnByID(target_id);
|
||||
if(test_spawn)
|
||||
KillSpawn(false, test_spawn, spawn, send_packet);
|
||||
}
|
||||
}
|
||||
grids->second->MSpawns.unlock_shared();
|
||||
}
|
||||
}
|
||||
MGridMaps.unlock_shared();
|
||||
}
|
||||
|
||||
void ZoneServer::SpawnSetByDistance(Spawn* spawn, float max_distance, string field, string value){
|
||||
if(!spawn)
|
||||
@ -7824,6 +7803,42 @@ std::vector<std::pair<int32, float>> ZoneServer::GetAttackableSpawnsByDistance(S
|
||||
return spawns_by_distance;
|
||||
}
|
||||
|
||||
std::vector<std::pair<int32, float>> ZoneServer::GetSpawnsByDistance(Spawn* spawn, float max_distance, bool include_players) {
|
||||
std::vector<std::pair<int32, float>> spawns_by_distance;
|
||||
auto loc = glm::vec3(spawn->GetX(), spawn->GetZ(), spawn->GetY());
|
||||
std::vector<int32> grids_by_radius;
|
||||
if(spawn->GetMap()) {
|
||||
grids_by_radius = GetGridsByLocation(spawn, loc, max_distance);
|
||||
}
|
||||
else {
|
||||
grids_by_radius.push_back(spawn->GetLocation());
|
||||
}
|
||||
|
||||
float tmp_dist = 0.0f;
|
||||
MGridMaps.lock_shared();
|
||||
std::vector<int32>::iterator grid_radius_itr;
|
||||
for(grid_radius_itr = grids_by_radius.begin(); grid_radius_itr != grids_by_radius.end(); grid_radius_itr++) {
|
||||
std::map<int32, GridMap*>::iterator grids = grid_maps.find((*grid_radius_itr));
|
||||
if(grids != grid_maps.end()) {
|
||||
grids->second->MSpawns.lock_shared();
|
||||
typedef map <int32, Spawn*> SpawnMapType;
|
||||
for( SpawnMapType::iterator it = grids->second->spawns.begin(); it != grids->second->spawns.end(); ++it ) {
|
||||
Spawn* test_spawn = it->second;
|
||||
if(test_spawn && test_spawn->Alive() && test_spawn->GetID() > 0 && test_spawn->GetID() != spawn->GetID() && test_spawn->IsEntity() &&
|
||||
(!test_spawn->IsPlayer() || include_players)){
|
||||
if(test_spawn->GetDistance(spawn) < max_distance)
|
||||
spawns_by_distance.push_back({test_spawn->GetID(), tmp_dist});
|
||||
}
|
||||
}
|
||||
grids->second->MSpawns.unlock_shared();
|
||||
}
|
||||
}
|
||||
MGridMaps.unlock_shared();
|
||||
std::sort(spawns_by_distance.begin(), spawns_by_distance.end(), compareByValue);
|
||||
|
||||
return spawns_by_distance;
|
||||
}
|
||||
|
||||
void ZoneServer::ResurrectSpawn(Spawn* spawn, Client* client) {
|
||||
if(!client || !spawn)
|
||||
return;
|
||||
|
@ -448,6 +448,7 @@ public:
|
||||
std::vector<int32> GetGridsByLocation(Spawn* originator, glm::vec3 loc, float distance);
|
||||
/// <summary>Gets spawns for a true AoE spell</summary>
|
||||
std::vector<std::pair<int32, float>> GetAttackableSpawnsByDistance(Spawn* spawn, float distance);
|
||||
std::vector<std::pair<int32, float>> GetSpawnsByDistance(Spawn* spawn, float max_distance, bool include_players);
|
||||
|
||||
// Comparator function to sort by the value (second element of the pair)
|
||||
static bool compareByValue(const std::pair<int32, float>& a, const std::pair<int32, float>& b) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user