Browse Source

Fixed SysClient setting client ready for updates, when it was sending keep alive, added sent wait state for spawns (500ms delay)

Image 2 years ago
parent
commit
5b9b2642f4

+ 42 - 23
EQ2/source/WorldServer/Player.cpp

@@ -52,7 +52,7 @@ Player::Player(){
 	char_id = 0;
 	group = 0;
 	appearance.pos.grid_id = 0;
-	spawn_index = 0;
+	spawn_index = 1;
 	info = 0;
 	movement_packet = 0;
 	fully_logged_in = false;
@@ -3259,10 +3259,10 @@ SpellEffects* Player::GetSpellEffects() {
 
 // call inside info_mutex
 void Player::ClearRemovalTimers(){
-	map<int32, SpawnRemoval*>::iterator itr;
-	for(itr = spawn_removal_list.begin(); itr != spawn_removal_list.end();) {
-		SpawnRemoval* sr = itr->second;
-		itr = spawn_removal_list.erase(itr);
+	map<int32, SpawnQueueState*>::iterator itr;
+	for(itr = spawn_state_list.begin(); itr != spawn_state_list.end();) {
+		SpawnQueueState* sr = itr->second;
+		itr = spawn_state_list.erase(itr);
 		safe_delete(sr);
 	}
 }
@@ -3802,8 +3802,8 @@ bool Player::SetSpawnSentState(Spawn* spawn, SpawnState state) {
 	bool val = true;
 	spawn_mutex.writelock(__FUNCTION__, __LINE__);
 	int16 index = GetIndexForSpawn(spawn);
-	if(index > 0 && state == SpawnState::SPAWN_STATE_SENDING) {
-		LogWrite(PLAYER__WARNING, 0, "Player", "Spawn ALREADY INDEXED for Player %s (%u).  Spawn %s (index %u) in state %u.", 
+	if(index > 0 && (state == SpawnState::SPAWN_STATE_SENDING)) {
+		LogWrite(PLAYER__WARNING, 0, "Player", "Spawn ALREADY INDEXED for Player %s (%u).  Spawn %s (index %u) attempted to state %u.", 
 			GetName(), GetCharacterID(), spawn->GetName(), index, state);
 		// we don't do anything this spawn is already populated by the player 
 	}
@@ -3816,33 +3816,47 @@ bool Player::SetSpawnSentState(Spawn* spawn, SpawnState state) {
 			itr->second = state;
 		else
 			spawn_packet_sent.insert(make_pair(spawn->GetID(), state));
-
-		if(state == SpawnState::SPAWN_STATE_REMOVING && 
-			spawn_removal_list.count(spawn->GetID()) == 0) {
-			spawn_removal_list.erase(spawn->GetID());
-			SpawnRemoval* removal = new SpawnRemoval;
+		if(state == SPAWN_STATE_SENT_WAIT) {
+			spawn_state_list.erase(spawn->GetID());
+			SpawnQueueState* removal = new SpawnQueueState;
+			removal->index_id = index;
+			removal->spawn_state_timer = Timer(500, true);
+			removal->spawn_state_timer.Start();
+			spawn_state_list.insert(make_pair(spawn->GetID(),removal));
+		}
+		else if(state == SpawnState::SPAWN_STATE_REMOVING && 
+			spawn_state_list.count(spawn->GetID()) == 0) {
+			spawn_state_list.erase(spawn->GetID());
+			SpawnQueueState* removal = new SpawnQueueState;
 			removal->index_id = index;
-			removal->spawn_removal_timer = Timer(1000, true);
-			removal->spawn_removal_timer.Start();
-			spawn_removal_list.insert(make_pair(spawn->GetID(),removal));
+			removal->spawn_state_timer = Timer(1000, true);
+			removal->spawn_state_timer.Start();
+			spawn_state_list.insert(make_pair(spawn->GetID(),removal));
 		}
 	}
 	spawn_mutex.releasewritelock(__FUNCTION__, __LINE__);
 	return val;
 }
 
-void Player::CheckSpawnRemovalQueue() {
+void Player::CheckSpawnStateQueue() {
 	if(!GetClient()->IsReadyForUpdates())
 		return;
 
 	spawn_mutex.writelock(__FUNCTION__, __LINE__);
-	map<int32, SpawnRemoval*>::iterator itr;
-	for(itr = spawn_removal_list.begin(); itr != spawn_removal_list.end();) {
-		if(itr->second->spawn_removal_timer.Check()) {
+	map<int32, SpawnQueueState*>::iterator itr;
+	for(itr = spawn_state_list.begin(); itr != spawn_state_list.end();) {
+		if(itr->second->spawn_state_timer.Check()) {
 			map<int32, int8>::iterator sent_itr = spawn_packet_sent.find(itr->first);
 			LogWrite(PLAYER__DEBUG, 0, "Player", "Spawn for Player %s (%u).  Spawn index %u in state %u.", 
 				GetName(), GetCharacterID(), itr->second->index_id, sent_itr->second);
 			switch(sent_itr->second) {
+				case SpawnState::SPAWN_STATE_SENT_WAIT: {
+					sent_itr->second = SpawnState::SPAWN_STATE_SENT;
+					SpawnQueueState* sr = itr->second;
+					itr = spawn_state_list.erase(itr);
+					safe_delete(sr);
+					break;
+				}
 				case SpawnState::SPAWN_STATE_REMOVING: {
 					if(itr->second->index_id) {
 						PacketStruct* packet = packet = configReader.getStruct("WS_DestroyGhostCmd", GetClient()->GetVersion());
@@ -3859,8 +3873,8 @@ void Player::CheckSpawnRemovalQueue() {
 				case SpawnState::SPAWN_STATE_REMOVING_SLEEP: {
 					map<int32, int8>::iterator sent_itr = spawn_packet_sent.find(itr->first);
 					sent_itr->second = SpawnState::SPAWN_STATE_REMOVED;
-					SpawnRemoval* sr = itr->second;
-					itr = spawn_removal_list.erase(itr);
+					SpawnQueueState* sr = itr->second;
+					itr = spawn_state_list.erase(itr);
 					safe_delete(sr);
 					break;
 				}
@@ -3890,7 +3904,7 @@ bool Player::IsSendingSpawn(int32 spawn_id){
 	bool ret = false;
 	spawn_mutex.readlock(__FUNCTION__, __LINE__);
 	map<int32, int8>::iterator itr = spawn_packet_sent.find(spawn_id);
-	if(itr != spawn_packet_sent.end() && itr->second == SpawnState::SPAWN_STATE_SENDING) {
+	if(itr != spawn_packet_sent.end() && (itr->second == SpawnState::SPAWN_STATE_SENDING || itr->second == SPAWN_STATE_SENT_WAIT)) {
 		ret = true;
 	}
 	spawn_mutex.releasereadlock(__FUNCTION__, __LINE__);
@@ -5511,6 +5525,7 @@ void Player::ResetSavedSpawns(){
 	player_spawn_id_map.clear();
 	player_spawn_id_map[1] = this;
 	player_spawn_reverse_id_map[this] = 1;
+	spawn_index = 1;
 	index_mutex.releasewritelock(__FUNCTION__, __LINE__);
 
 	m_playerSpawnQuestsRequired.writelock(__FUNCTION__, __LINE__);
@@ -5557,7 +5572,11 @@ void Player::SetReturningFromLD(bool val){
 		info_xor_size = 0;
 		vis_xor_size = 0;
 		
-		spawn_index = 0;
+		index_mutex.writelock(__FUNCTION__, __LINE__);
+		player_spawn_id_map[1] = this;
+		player_spawn_reverse_id_map[this] = 1;
+		spawn_index = 1;
+		index_mutex.releasewritelock(__FUNCTION__, __LINE__);
 	}
 	
 	returning_from_ld = val;

+ 9 - 8
EQ2/source/WorldServer/Player.h

@@ -170,10 +170,11 @@ struct SpellBookEntry{
 enum SpawnState{
 	SPAWN_STATE_NONE=0,
 	SPAWN_STATE_SENDING=1,
-	SPAWN_STATE_SENT=2,
-	SPAWN_STATE_REMOVING=3,
-	SPAWN_STATE_REMOVING_SLEEP=4,
-	SPAWN_STATE_REMOVED=5
+	SPAWN_STATE_SENT_WAIT=2,
+	SPAWN_STATE_SENT=3,
+	SPAWN_STATE_REMOVING=4,
+	SPAWN_STATE_REMOVING_SLEEP=5,
+	SPAWN_STATE_REMOVED=6
 };
 #define QUICKBAR_NORMAL		1
 #define QUICKBAR_INV_SLOT	2
@@ -211,8 +212,8 @@ struct LoginAppearances {
 	bool	update_needed;
 };
 
-struct SpawnRemoval {
-	Timer spawn_removal_timer;
+struct SpawnQueueState {
+	Timer spawn_state_timer;
 	int16 index_id;
 };
 
@@ -434,7 +435,7 @@ public:
 	bool IsSendingSpawn(int32 spawn_id);
 	bool IsRemovingSpawn(int32 spawn_id);
 	bool SetSpawnSentState(Spawn* spawn, SpawnState state);
-	void CheckSpawnRemovalQueue();
+	void CheckSpawnStateQueue();
 	void SetSideSpeed(float side_speed, bool updateFlags = true) {
 		SetPos(&appearance.pos.SideSpeed, side_speed, updateFlags);
 	}
@@ -1031,7 +1032,7 @@ private:
 	map<int32, string>	spawn_info_packet_list;
 	map<int32, string>	spawn_pos_packet_list;
 	map<int32, int8> spawn_packet_sent;
-	map<int32, SpawnRemoval*> spawn_removal_list;
+	map<int32, SpawnQueueState*> spawn_state_list;
 	uchar*				movement_packet;
 	uchar*				old_movement_packet;
 	uchar*				spell_orig_packet;

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

@@ -2230,7 +2230,7 @@ void Spawn::InitializePosPacketData(Player* player, PacketStruct* packet, bool b
 		packet->setDataByName("pos_move_type", 16);
 	}
 
-	if (!IsPlayer())
+	if (!IsPlayer()) // has to be 2 or NPC's warp around when moving
 		packet->setDataByName("pos_movement_mode", 2);
 	
 	if(version <= 910)

+ 0 - 10
EQ2/source/WorldServer/Zone/map.cpp

@@ -361,11 +361,6 @@ bool Map::LoadV2(FILE* f) {
 	fread(&m_MaxX, sizeof(float), 1, f);
 	fread(&m_MaxZ, sizeof(float), 1, f);
 
-	// Calculate how many cells we need
-	// in both the X and Z direction
-	float width = m_MaxX - m_MinX;
-	float height = m_MaxZ - m_MinZ;
-
 	// Read the number of grids
 	int32 NumGrids;
 	fread(&NumGrids, sizeof(int32), 1, f);
@@ -497,11 +492,6 @@ bool Map::LoadV2Deflated(FILE* f) {
 	srcbuf->sgetn(buf,sizeof(float));
 	memcpy(&m_MaxZ,&buf[0],sizeof(float));
 
-	// Calculate how many cells we need
-	// in both the X and Z direction
-	float width = m_MaxX - m_MinX;
-	float height = m_MaxZ - m_MinZ;
-
 	// Read the number of grids
 	int32 NumGrids;
 	srcbuf->sgetn(buf,sizeof(int32));

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

@@ -1068,13 +1068,6 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 		safe_delete(request);
 		break;
 	}
-	case OP_SysClient: {
-		LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_SysClient", opcode, opcode);
-		LogWrite(CCLIENT__DEBUG, 0, "Client", "Client '%s' (%u) is ready for spawn updates.", GetPlayer()->GetName(), GetPlayer()->GetCharacterID());
-		SetReadyForUpdates();
-		ProcessStateCommands();
-		break;
-	}
 	case OP_MapRequest: {
 		LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_MapRequest", opcode, opcode);
 		PacketStruct* packet = configReader.getStruct("WS_MapRequest", GetVersion());
@@ -1647,15 +1640,23 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 		GetCurrentZone()->GetTradeskillMgr()->StopCrafting(this);
 		break;
 	}
+	case OP_SysClient:
 	case OP_SignalMsg: {
+		LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_SysClient/OP_SignalMsg", opcode, opcode);
+
 		PacketStruct* packet = configReader.getStruct("WS_Signal", GetVersion());
 		if (packet) {
 			packet->LoadPacketData(app->pBuffer, app->size);
 			EQ2_16BitString str = packet->getType_EQ2_16BitString_ByName("signal");
 			if (str.size > 0) {
 				if (strcmp(str.data.c_str(), "sys_client_avatar_ready") == 0) {
+					LogWrite(CCLIENT__DEBUG, 0, "Client", "Client '%s' (%u) is ready for spawn updates.", GetPlayer()->GetName(), GetPlayer()->GetCharacterID());
 					SetReadyForUpdates();
 					GetPlayer()->SendSpawnChanges(true);
+					ProcessStateCommands();
+				}
+				else {
+					LogWrite(CCLIENT__WARNING, 0, "Player %s reported SysClient/SignalMsg state %s.", GetPlayer()->GetName(), str.data.c_str());
 				}
 				const char* zone_script = world.GetZoneScript(player->GetZone()->GetZoneID());
 				if (zone_script && lua_interface)
@@ -3019,7 +3020,7 @@ bool Client::Process(bool zone_process) {
 	}
 
 	if(spawn_removal_timer.Check() && GetPlayer()) {
-		GetPlayer()->CheckSpawnRemovalQueue();
+		GetPlayer()->CheckSpawnStateQueue();
 	}
 
 	if (delayedLogin && delayTimer.Enabled() && delayTimer.Check())

+ 1 - 1
EQ2/source/WorldServer/zoneserver.cpp

@@ -3374,7 +3374,7 @@ void ZoneServer::SendSpawn(Spawn* spawn, Client* client){
 		if(outapp)
 			client->QueuePacket(outapp, true);
 
-		client->GetPlayer()->SetSpawnSentState(spawn, SpawnState::SPAWN_STATE_SENT);
+		client->GetPlayer()->SetSpawnSentState(spawn, SpawnState::SPAWN_STATE_SENT_WAIT);
 	}
 
 	/*