Prevent accessing spawn list outside of read lock, removal of pending spawn removals (redundant)
This commit is contained in:
parent
9ef48d3bab
commit
b7f56e3b73
@ -294,7 +294,7 @@ void Entity::MeleeAttack(Spawn* victim, float distance, bool primary, bool multi
|
||||
DamageSpawn((Entity*)victim, DAMAGE_PACKET_TYPE_SIMPLE_CRIT_DMG, damage_type, min_damage, max_damage, 0);
|
||||
}
|
||||
else*/
|
||||
DamageSpawn((Entity*)victim, DAMAGE_PACKET_TYPE_SIMPLE_DAMAGE, damage_type, min_damage, max_damage, 0);
|
||||
DamageSpawn((Entity*)victim, DAMAGE_PACKET_TYPE_SIMPLE_DAMAGE, damage_type, min_damage, max_damage, 0, 0, false, false, false, false, nullptr, false, true);
|
||||
if (!multi_attack) {
|
||||
CheckProcs(PROC_TYPE_OFFENSIVE, victim);
|
||||
CheckProcs(PROC_TYPE_PHYSICAL_OFFENSIVE, victim);
|
||||
@ -1057,7 +1057,7 @@ Skill* Entity::GetSkillByWeaponType(int8 type, int8 damage_type, bool update) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_damage, int32 high_damage, const char* spell_name, int8 crit_mod, bool is_tick, bool no_calcs, bool ignore_attacker, bool take_power, LuaSpell* spell, bool skip_check_wards) {
|
||||
bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_damage, int32 high_damage, const char* spell_name, int8 crit_mod, bool is_tick, bool no_calcs, bool ignore_attacker, bool take_power, LuaSpell* spell, bool skip_check_wards, bool is_melee_spawn) {
|
||||
if(spell) {
|
||||
spell->is_damage_spell = true;
|
||||
}
|
||||
@ -1236,7 +1236,7 @@ bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_
|
||||
}
|
||||
|
||||
if (victim->GetHP() <= 0)
|
||||
KillSpawn(victim, type, damage_type, blow_type);
|
||||
KillSpawn(victim, type, damage_type, blow_type, is_melee_spawn);
|
||||
else {
|
||||
victim->CheckProcs(PROC_TYPE_DEFENSIVE, this);
|
||||
if (spell_name)
|
||||
@ -1439,7 +1439,7 @@ bool Entity::CheckInterruptSpell(Entity* attacker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Entity::KillSpawn(Spawn* dead, int8 type, int8 damage_type, int16 kill_blow_type) {
|
||||
void Entity::KillSpawn(Spawn* dead, int8 type, int8 damage_type, int16 kill_blow_type, bool is_melee_spawn) {
|
||||
if(!dead)
|
||||
return;
|
||||
|
||||
@ -1479,7 +1479,7 @@ void Entity::KillSpawn(Spawn* dead, int8 type, int8 damage_type, int16 kill_blow
|
||||
dead->ClearRunningLocations();
|
||||
dead->CalculateRunningLocation(true);
|
||||
|
||||
GetZone()->KillSpawn(true, dead, this, true, type, damage_type, kill_blow_type);
|
||||
GetZone()->KillSpawn(is_melee_spawn, dead, this, true, type, damage_type, kill_blow_type);
|
||||
}
|
||||
|
||||
void Entity::HandleDeathExperienceDebt(Spawn* killer)
|
||||
@ -1552,7 +1552,7 @@ void Player::ProcessCombat() {
|
||||
return;
|
||||
|
||||
//If no target delete combat_target and return out
|
||||
Spawn* Target = GetZone()->GetSpawnByID(target);
|
||||
Spawn* Target = GetZone()->GetSpawnByID(target, true);
|
||||
if (!Target) {
|
||||
combat_target = 0;
|
||||
if (target > 0) {
|
||||
|
@ -1563,12 +1563,12 @@ public:
|
||||
int8 DetermineHit(Spawn* victim, int8 type, int8 damage_type, float ToHitBonus, bool is_caster_spell, LuaSpell* lua_spell = nullptr);
|
||||
float GetDamageTypeResistPercentage(int8 damage_type);
|
||||
Skill* GetSkillByWeaponType(int8 type, int8 damage_type, bool update);
|
||||
bool DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_damage, int32 high_damage, const char* spell_name, int8 crit_mod = 0, bool is_tick = false, bool no_damage_calcs = false, bool ignore_attacker = false, bool take_power = false, LuaSpell* spell = 0, bool skip_check_wards = false);
|
||||
bool DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_damage, int32 high_damage, const char* spell_name, int8 crit_mod = 0, bool is_tick = false, bool no_damage_calcs = false, bool ignore_attacker = false, bool take_power = false, LuaSpell* spell = 0, bool skip_check_wards = false, bool is_melee_spawn = false);
|
||||
float CalculateMitigation(int8 type = DAMAGE_PACKET_TYPE_SIMPLE_DAMAGE, int8 damage_type = 0, int16 attacker_level = 0, bool for_pvp = false);
|
||||
void AddHate(Entity* attacker, sint32 hate, bool ignore_pet_behavior = false);
|
||||
bool CheckInterruptSpell(Entity* attacker);
|
||||
bool CheckFizzleSpell(LuaSpell* spell);
|
||||
void KillSpawn(Spawn* dead, int8 type = 0, int8 damage_type = 0, int16 kill_blow_type = 0);
|
||||
void KillSpawn(Spawn* dead, int8 type = 0, int8 damage_type = 0, int16 kill_blow_type = 0, bool is_melee_spawn = false);
|
||||
void HandleDeathExperienceDebt(Spawn* killer);
|
||||
void SetAttackDelay(bool primary = false, bool ranged = false);
|
||||
float CalculateAttackSpeedMod();
|
||||
|
@ -175,8 +175,6 @@ ZoneServer::ZoneServer(const char* name) {
|
||||
tradeskillMgr = nullptr;
|
||||
watchdogTimestamp = Timer::GetCurrentTime2();
|
||||
|
||||
MPendingSpawnRemoval.SetName("ZoneServer::MPendingSpawnRemoval");
|
||||
|
||||
lifetime_client_count = 0;
|
||||
|
||||
groupraidMinLevel = 0;
|
||||
@ -311,6 +309,7 @@ void ZoneServer::Init()
|
||||
shutdownTimer.Disable();
|
||||
spawn_range.Start(rule_manager.GetGlobalRule(R_Zone, CheckAttackPlayer)->GetInt32());
|
||||
aggro_timer.Start(rule_manager.GetGlobalRule(R_Zone, CheckAttackNPC)->GetInt32());
|
||||
delete_timer.Start(1000);
|
||||
/* Weather stuff */
|
||||
InitWeather();
|
||||
|
||||
@ -1528,21 +1527,13 @@ void ZoneServer::DeleteSpawns(bool delete_all) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MPendingSpawnRemoval.readlock(__FUNCTION__, __LINE__);
|
||||
if(!delete_all && m_pendingSpawnRemove.count(spawn->GetID())) {
|
||||
to_keep.emplace_back(entry);
|
||||
MPendingSpawnRemoval.releasereadlock(__FUNCTION__, __LINE__);
|
||||
continue;
|
||||
}
|
||||
MPendingSpawnRemoval.releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
||||
lua_interface->SetLuaUserDataStale(spawn);
|
||||
|
||||
if (spellProcess) {
|
||||
spellProcess->RemoveCaster(spawn, true);
|
||||
}
|
||||
|
||||
if(movementMgr != nullptr) {
|
||||
if(spawn->IsEntity() && movementMgr != nullptr) {
|
||||
movementMgr->RemoveMob((Entity*)spawn);
|
||||
}
|
||||
|
||||
@ -1890,10 +1881,7 @@ bool ZoneServer::SpawnProcess(){
|
||||
bool spawnRange = spawn_range.Check();
|
||||
bool checkRemove = spawn_check_remove.Check();
|
||||
bool aggroCheck = aggro_timer.Check();
|
||||
vector<int32> pending_spawn_list_remove;
|
||||
|
||||
// Check to see if there are any spawn id's that need to be removed from the spawn list, if so remove them all
|
||||
ProcessSpawnRemovals();
|
||||
bool deleteTimer = delete_timer.Check();
|
||||
|
||||
map<int32, Spawn*>::iterator itr;
|
||||
if (spawnRange || checkRemove)
|
||||
@ -1960,40 +1948,16 @@ bool ZoneServer::SpawnProcess(){
|
||||
CombatProcess(spawn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unable to get a valid spawn, lets add the id to another list to remove from the spawn list after this loop is finished
|
||||
pending_spawn_list_remove.push_back(itr->first);
|
||||
}
|
||||
|
||||
}
|
||||
MSpawnList.releasereadlock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
// Check to see if there are any spawn id's that need to be removed from the spawn list, if so remove them all
|
||||
if (pending_spawn_list_remove.size() > 0) {
|
||||
MSpawnList.writelock(__FUNCTION__, __LINE__);
|
||||
vector<int32>::iterator itr2;
|
||||
for (itr2 = pending_spawn_list_remove.begin(); itr2 != pending_spawn_list_remove.end(); itr2++) {
|
||||
spawn_list.erase(*itr2);
|
||||
subspawn_list[SUBSPAWN_TYPES::COLLECTOR].erase(*itr2);
|
||||
|
||||
std::map<int32,int32>::iterator hsmitr = housing_spawn_map.find(*itr2);
|
||||
if(hsmitr != housing_spawn_map.end()) {
|
||||
subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].erase(hsmitr->second);
|
||||
housing_spawn_map.erase(hsmitr);
|
||||
}
|
||||
}
|
||||
|
||||
pending_spawn_list_remove.clear();
|
||||
MSpawnList.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
// Double Check to see if there are any spawn id's that need to be removed from the spawn list, if so remove them before we replace with pending spawns
|
||||
// and also potentially further down when we delete the Spawn* in DeleteSpawns(false)
|
||||
ProcessSpawnRemovals();
|
||||
|
||||
// Check to see if there are spawns waiting to be added to the spawn list, if so add them all
|
||||
if (pending_spawn_list_add.size() > 0) {
|
||||
MPendingSpawnListAdd.readlock(__FUNCTION__, __LINE__);
|
||||
int32 pending_count = pending_spawn_list_add.size();
|
||||
MPendingSpawnListAdd.releasereadlock(__FUNCTION__, __LINE__);
|
||||
if (pending_count > 0) {
|
||||
ProcessPendingSpawns();
|
||||
}
|
||||
|
||||
@ -2011,7 +1975,7 @@ bool ZoneServer::SpawnProcess(){
|
||||
|
||||
|
||||
// Delete unused spawns, do this last
|
||||
if(!zoneShuttingDown)
|
||||
if(!zoneShuttingDown && deleteTimer)
|
||||
DeleteSpawns(false);
|
||||
|
||||
// Nothing should come after this
|
||||
@ -4706,7 +4670,7 @@ void ZoneServer::KillSpawnByDistance(Spawn* spawn, float max_distance, bool incl
|
||||
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)
|
||||
KillSpawn(true, test_spawn, spawn, send_packet);
|
||||
KillSpawn(false, test_spawn, spawn, send_packet);
|
||||
}
|
||||
}
|
||||
grids->second->MSpawns.unlock_shared();
|
||||
@ -4832,10 +4796,6 @@ void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool
|
||||
|
||||
spawn->SetDeletedSpawn(true);
|
||||
|
||||
// we will remove the spawn ptr and entry in the spawn_list later.. it is not safe right now (lua? client process? spawn process? etc? too many factors)
|
||||
if(erase_from_spawn_list)
|
||||
AddPendingSpawnRemove(spawn->GetID());
|
||||
|
||||
if(respawn && !spawn->IsPlayer() && spawn->GetSpawnLocationID() > 0) {
|
||||
LogWrite(ZONE__DEBUG, 3, "Zone", "Handle NPC Respawn for '%s'.", spawn->GetName());
|
||||
AddRespawn(spawn);
|
||||
@ -5131,7 +5091,7 @@ void ZoneServer::ProcessFaction(Spawn* spawn, Client* client)
|
||||
}
|
||||
|
||||
void ZoneServer::Despawn(Spawn* spawn, int32 timer){
|
||||
if (spawn && movementMgr != nullptr) {
|
||||
if (spawn && spawn->IsEntity() && movementMgr != nullptr) {
|
||||
movementMgr->RemoveMob((Entity*)spawn);
|
||||
}
|
||||
if(!spawn || spawn->IsPlayer())
|
||||
@ -5453,7 +5413,7 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
|
||||
spellProcess->RemoveSpellFromQueue((Player*)dead, true);
|
||||
|
||||
if (dead->IsNPC())
|
||||
((NPC*)dead)->Brain()->ClearHate(!spawnListLocked);
|
||||
((NPC*)dead)->Brain()->ClearHate(spawnListLocked);
|
||||
|
||||
safe_delete(encounter);
|
||||
|
||||
@ -9164,36 +9124,6 @@ Spawn* ZoneServer::GetSpawnFromUniqueItemID(int32 unique_id)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ZoneServer::AddPendingSpawnRemove(int32 id)
|
||||
{
|
||||
MPendingSpawnRemoval.writelock(__FUNCTION__, __LINE__);
|
||||
m_pendingSpawnRemove.insert(make_pair(id,true));
|
||||
MPendingSpawnRemoval.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
void ZoneServer::ProcessSpawnRemovals()
|
||||
{
|
||||
MSpawnList.writelock(__FUNCTION__, __LINE__);
|
||||
MPendingSpawnRemoval.writelock(__FUNCTION__, __LINE__);
|
||||
if (m_pendingSpawnRemove.size() > 0) {
|
||||
map<int32,bool>::iterator itr2;
|
||||
for (itr2 = m_pendingSpawnRemove.begin(); itr2 != m_pendingSpawnRemove.end(); itr2++) {
|
||||
spawn_list.erase(itr2->first);
|
||||
subspawn_list[SUBSPAWN_TYPES::COLLECTOR].erase(itr2->first);
|
||||
|
||||
std::map<int32,int32>::iterator hsmitr = housing_spawn_map.find(itr2->first);
|
||||
if(hsmitr != housing_spawn_map.end()) {
|
||||
subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].erase(hsmitr->second);
|
||||
housing_spawn_map.erase(hsmitr);
|
||||
}
|
||||
}
|
||||
|
||||
m_pendingSpawnRemove.clear();
|
||||
}
|
||||
MPendingSpawnRemoval.releasewritelock(__FUNCTION__, __LINE__);
|
||||
MSpawnList.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
void ZoneServer::AddSpawnToGroup(Spawn* spawn, int32 group_id)
|
||||
{
|
||||
if( spawn->GetSpawnGroupID() > 0 )
|
||||
|
@ -706,9 +706,6 @@ public:
|
||||
void SetWatchdogTime(int32 time) { watchdogTimestamp = time; }
|
||||
void CancelThreads();
|
||||
|
||||
void AddPendingSpawnRemove(int32 id);
|
||||
void ProcessSpawnRemovals();
|
||||
|
||||
bool SendRemoveSpawn(Client* client, Spawn* spawn, PacketStruct* packet = 0, bool delete_spawn = false);
|
||||
|
||||
void AddSpawnToGroup(Spawn* spawn, int32 group_id);
|
||||
@ -924,6 +921,7 @@ private:
|
||||
Timer widget_timer;
|
||||
Timer queue_updates;
|
||||
Timer shutdownDelayTimer;
|
||||
Timer delete_timer;
|
||||
|
||||
/* Enums */
|
||||
Instance_Type InstanceType;
|
||||
@ -1029,9 +1027,6 @@ private:
|
||||
|
||||
int32 watchdogTimestamp;
|
||||
|
||||
std::map<int32, bool> m_pendingSpawnRemove;
|
||||
Mutex MPendingSpawnRemoval;
|
||||
|
||||
std::map<int32, int32> lua_queued_state_commands;
|
||||
std::map<int32, std::map<std::string, float>> lua_spawn_update_command;
|
||||
std::mutex MLuaQueueStateCmd;
|
||||
|
Loading…
x
Reference in New Issue
Block a user