Browse Source

House item placement updated to prevent sending move spawn packet too early, causing client to become the object/crash

Fix #382
Image 2 years ago
parent
commit
3bf1b2554a

+ 5 - 6
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -3745,12 +3745,14 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						client->SetTempPlacementSpawn(nullptr);
 					}
 
-					Spawn* spawn = new Object();
+					Object* obj = new Object();
+					Spawn* spawn = (Spawn*)obj;
 					memset(&spawn->appearance, 0, sizeof(spawn->appearance));
-					spawn->SetID(Spawn::NextID());
+					strcpy(spawn->appearance.name, "temp");
 					spawn->SetX(client->GetPlayer()->GetX());
 					spawn->SetY(client->GetPlayer()->GetY());
 					spawn->SetZ(client->GetPlayer()->GetZ());
+					spawn->appearance.pos.collision_radius = 32;
 					spawn->SetHeading(client->GetPlayer()->GetHeading());
 					spawn->SetSpawnOrigX(spawn->GetX());
 					spawn->SetSpawnOrigY(spawn->GetY());
@@ -3762,12 +3764,9 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					spawn->appearance.pos.grid_id = client->GetPlayer()->appearance.pos.grid_id;
 					spawn->SetModelType(item && item->generic_info.appearance_id ? item->generic_info.appearance_id : 1472);
 					spawn->SetZone(client->GetCurrentZone());
-					client->GetCurrentZone()->SendSpawn(spawn, client);
-
 					client->SetTempPlacementSpawn(spawn);
 					client->SetPlacementUniqueItemID(uniqueid);
-
-					client->SendMoveObjectMode(spawn, 0);
+					client->GetCurrentZone()->AddSpawn(spawn);
 				}
 			}
 			break;

+ 25 - 9
EQ2/source/WorldServer/client.cpp

@@ -122,7 +122,7 @@ extern ChestTrapList chest_trap_list;
 
 using namespace std;
 
-Client::Client(EQStream* ieqs) : pos_update(125), quest_pos_timer(2000), lua_debug_timer(30000), delayTimer(500), transmuteID(0) {
+Client::Client(EQStream* ieqs) : pos_update(125), quest_pos_timer(2000), lua_debug_timer(30000), delayTimer(500), transmuteID(0), temp_placement_timer(10) {
 	eqs = ieqs;
 	ip = eqs->GetrIP();
 	port = ntohs(eqs->GetrPort());
@@ -207,6 +207,7 @@ Client::Client(EQStream* ieqs) : pos_update(125), quest_pos_timer(2000), lua_deb
 	player_loading_complete = false;
 	MItemDetails.SetName("Client::MItemDetails");
 	MSpellDetails.SetName("Client::MSpellDetails");
+	hasSentTempPlacementSpawn = false;
 }
 
 Client::~Client() {
@@ -232,6 +233,12 @@ Client::~Client() {
 
 
 void Client::RemoveClientFromZone() {
+	if (GetTempPlacementSpawn() && GetCurrentZone()) {
+		Spawn* tmp = GetTempPlacementSpawn();
+		SetTempPlacementSpawn(nullptr);
+		GetCurrentZone()->RemoveSpawn(tmp, true, false, true, true, true);
+	}
+
 	if(player && player->GetZone())
 		player->GetZone()->GetSpellProcess()->RemoveSpellTimersFromSpawn(player, true, false, true, true);
 
@@ -257,13 +264,6 @@ void Client::RemoveClientFromZone() {
 	safe_delete(pending_last_name);
 	safe_delete_array(incoming_paperdoll.image_bytes);
 
-	if (GetTempPlacementSpawn())
-	{
-		Spawn* tmp = GetTempPlacementSpawn();
-		delete tmp;
-		SetTempPlacementSpawn(nullptr);
-	}
-
 	MDeletePlayer.writelock(__FUNCTION__, __LINE__);
 	if (player && !player->GetPendingDeletion())
 		safe_delete(player);
@@ -1302,9 +1302,9 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 		if (GetTempPlacementSpawn())
 		{
 			Spawn* tmp = GetTempPlacementSpawn();
-			GetCurrentZone()->RemoveSpawn(tmp, true, true, true, true, true);
 			SetTempPlacementSpawn(nullptr);
 			SetPlacementUniqueItemID(0);
+			GetCurrentZone()->RemoveSpawn(tmp, true, false, true, true, true);
 			break; // break out early if we are tied to a temp spawn
 		}
 
@@ -3032,6 +3032,13 @@ bool Client::Process(bool zone_process) {
 	}
 	MSaveSpellStateMutex.unlock();
 
+	if (temp_placement_timer.Check()) {
+		if(GetTempPlacementSpawn() && GetPlayer()->WasSentSpawn(GetTempPlacementSpawn()->GetID()) && !hasSentTempPlacementSpawn) {
+			SendMoveObjectMode(GetTempPlacementSpawn(), 0);
+			hasSentTempPlacementSpawn = true;
+			temp_placement_timer.Disable();
+		}
+	}
 	if (pos_update.Check())
 	{
 		ProcessStateCommands();
@@ -10649,4 +10656,13 @@ void Client::UpdateSentSpellList() {
 		QueuePacket(app);
 	}
 	MSpellDetails.releasereadlock(__FUNCTION__, __LINE__);
+}
+
+void Client::SetTempPlacementSpawn(Spawn* tmp) { 
+	tempPlacementSpawn = tmp;
+	hasSentTempPlacementSpawn = false;
+	if(tempPlacementSpawn)
+		temp_placement_timer.Start();
+	else
+		temp_placement_timer.Disable();
 }

+ 4 - 1
EQ2/source/WorldServer/client.h

@@ -423,7 +423,8 @@ public:
 	void SendHailCommand(Spawn* target);
 	void SendDefaultCommand(Spawn* spawn, const char* command, float distance);
 
-	void SetTempPlacementSpawn(Spawn* tmp) { tempPlacementSpawn = tmp; }
+	void SetTempPlacementSpawn(Spawn* tmp);
+	
 	Spawn* GetTempPlacementSpawn() { return tempPlacementSpawn; }
 
 	void SetPlacementUniqueItemID(int32 id) { placement_unique_item_id = id; }
@@ -587,6 +588,7 @@ private:
 	Timer	pos_update;
 	Timer	quest_pos_timer;
 	Timer	lua_debug_timer;
+	Timer	temp_placement_timer;
 	bool	player_pos_changed;
 	bool HandlePacket(EQApplicationPacket *app);
 	EQStream* eqs;
@@ -621,6 +623,7 @@ private:
 	Spawn* tempPlacementSpawn;
 	int32 placement_unique_item_id;
 	bool hasOwnerOrEditAccess;
+	bool hasSentTempPlacementSpawn;
 
 	int32 temporary_transport_id;