Browse Source

Added 'deleted' spawn state, in which we do not continue sending a spawn after it is removed from game world (but still existing in the spawn list)

This will prevent a potential crash when the client logging in maps a spawn that is to be deleted.
Image 2 years ago
parent
commit
9a4829a27d

+ 3 - 1
EQ2/source/WorldServer/Player.cpp

@@ -5027,7 +5027,9 @@ bool Player::ShouldSendSpawn(Spawn* spawn){
 	// Think invalid spawns are coming from the mutex list, if spawn is invalid return false.
 	try
 	{
-		if((WasSentSpawn(spawn->GetID()) == false || NeedsSpawnResent(spawn)) && (!spawn->IsPrivateSpawn() || spawn->AllowedAccess(this)))
+		if(spawn->IsDeletedSpawn())
+			return false;
+		else if((WasSentSpawn(spawn->GetID()) == false || NeedsSpawnResent(spawn)) && (!spawn->IsPrivateSpawn() || spawn->AllowedAccess(this)))
 			return true;
 	}
 	catch (...)

+ 1 - 0
EQ2/source/WorldServer/Spawn.cpp

@@ -130,6 +130,7 @@ Spawn::Spawn(){
 	rail_id = 0;
 	is_omitted_by_db_flag = false;
 	loot_tier = 0;
+	deleted_spawn = false;
 }
 
 Spawn::~Spawn(){

+ 4 - 0
EQ2/source/WorldServer/Spawn.h

@@ -1251,6 +1251,8 @@ public:
 	int32 GetLootTier() { return loot_tier; }
 	void SetLootTier(int32 tier) { loot_tier = tier; }
 
+	void SetDeletedSpawn(bool val) { deleted_spawn = val; }
+	bool IsDeletedSpawn() { return deleted_spawn; }
 protected:
 
 	bool	has_quests_required;
@@ -1358,6 +1360,8 @@ private:
 	bool is_omitted_by_db_flag; // this particular spawn is omitted by an expansion or holiday flag
 
 	int32 loot_tier;
+
+	bool deleted_spawn;
 };
 
 #endif

+ 7 - 0
EQ2/source/WorldServer/zoneserver.cpp

@@ -729,6 +729,7 @@ void ZoneServer::ProcessDepop(bool respawns_allowed, bool repop) {
 			spawn = itr->second;
 			if(spawn && !spawn->IsPlayer()){
 				bool dispatched = false;
+				spawn->SetDeletedSpawn(true);
 				if(spawn->IsBot())
 				{
 					((Bot*)spawn)->Camp(true);
@@ -837,10 +838,14 @@ void ZoneServer::RepopSpawns(Client* client, Spawn* in_spawn){
 		vector<Spawn*>::iterator itr;
 		for(itr = spawns->begin(); itr != spawns->end(); itr++){
 			spawn = *itr;
+			spawn->SetDeletedSpawn(true);
 			SendRemoveSpawn(client, spawn, packet);
 		}
 	}
 	safe_delete(spawns);
+	if(in_spawn)
+		in_spawn->SetDeletedSpawn(true);
+
 	SendRemoveSpawn(client, in_spawn, packet);
 	spawn_check_add.Trigger();
 	safe_delete(packet);
@@ -3947,6 +3952,8 @@ void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool
 	if (spawn_expire_timers.count(spawn->GetID()) > 0)
 		spawn_expire_timers.erase(spawn->GetID());
 	
+	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());