mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-11-04 14:42:02 +00:00 
			
		
		
		
	Merge pull request #590 Fix instances not stopping on all players leaving
Address order of deletion of entities on server to allow scripted activities to properly remove players
This commit is contained in:
		@@ -99,22 +99,6 @@ Entity::~Entity() {
 | 
			
		||||
		m_Character->SaveXMLToDatabase();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (IsPlayer()) {
 | 
			
		||||
        Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity();
 | 
			
		||||
        for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
 | 
			
		||||
            script->OnPlayerExit(zoneControl, this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::vector<Entity*> scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPTED_ACTIVITY);
 | 
			
		||||
        for (Entity* scriptEntity : scriptedActs) {
 | 
			
		||||
            if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
 | 
			
		||||
                for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
 | 
			
		||||
                    script->OnPlayerExit(scriptEntity, this);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CancelAllTimers();
 | 
			
		||||
	CancelCallbackTimers();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -217,37 +217,42 @@ void EntityManager::UpdateEntities(const float deltaTime) {
 | 
			
		||||
 | 
			
		||||
	m_EntitiesToKill.clear();
 | 
			
		||||
 | 
			
		||||
	for (const auto& entry : m_EntitiesToDelete)
 | 
			
		||||
	for (const auto entry : m_EntitiesToDelete)
 | 
			
		||||
	{
 | 
			
		||||
		auto* entity = GetEntity(entry);
 | 
			
		||||
		// Get all this info first before we delete the player.
 | 
			
		||||
		auto entityToDelete = GetEntity(entry);
 | 
			
		||||
 | 
			
		||||
		m_Entities.erase(entry);
 | 
			
		||||
		auto networkIdToErase = entityToDelete->GetNetworkId();
 | 
			
		||||
 | 
			
		||||
		const auto& iter = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entity);
 | 
			
		||||
		const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete);
 | 
			
		||||
 | 
			
		||||
		if (iter != m_EntitiesToGhost.end())
 | 
			
		||||
		if (entityToDelete)
 | 
			
		||||
		{
 | 
			
		||||
			m_EntitiesToGhost.erase(iter);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (entity != nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			if (entity->GetNetworkId() != 0)
 | 
			
		||||
			// If we are a player run through the player destructor.
 | 
			
		||||
			if (entityToDelete->IsPlayer())
 | 
			
		||||
			{
 | 
			
		||||
				m_LostNetworkIds.push(entity->GetNetworkId());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (entity->IsPlayer())
 | 
			
		||||
			{
 | 
			
		||||
				delete dynamic_cast<Player*>(entity);
 | 
			
		||||
				delete dynamic_cast<Player*>(entityToDelete);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				delete entity;
 | 
			
		||||
				delete entityToDelete;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			entity = nullptr;
 | 
			
		||||
			entityToDelete = nullptr;
 | 
			
		||||
 | 
			
		||||
			if (networkIdToErase != 0)
 | 
			
		||||
			{
 | 
			
		||||
				m_LostNetworkIds.push(networkIdToErase);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (ghostingToDelete != m_EntitiesToGhost.end())
 | 
			
		||||
		{
 | 
			
		||||
			m_EntitiesToGhost.erase(ghostingToDelete);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_Entities.erase(entry);
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_EntitiesToDelete.clear();
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
#include "dZoneManager.h"
 | 
			
		||||
#include "CharacterComponent.h"
 | 
			
		||||
#include "Mail.h"
 | 
			
		||||
#include "CppScripts.h"
 | 
			
		||||
 | 
			
		||||
std::vector<Player*> Player::m_Players = {};
 | 
			
		||||
 | 
			
		||||
@@ -329,5 +330,21 @@ Player::~Player()
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (IsPlayer()) {
 | 
			
		||||
        Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity();
 | 
			
		||||
        for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
 | 
			
		||||
            script->OnPlayerExit(zoneControl, this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::vector<Entity*> scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPTED_ACTIVITY);
 | 
			
		||||
        for (Entity* scriptEntity : scriptedActs) {
 | 
			
		||||
            if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
 | 
			
		||||
                for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
 | 
			
		||||
                    script->OnPlayerExit(scriptEntity, this);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Players.erase(iter);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -91,9 +91,27 @@ void NjMonastryBossInstance::OnPlayerLoaded(Entity *self, Entity *player) {
 | 
			
		||||
 | 
			
		||||
void NjMonastryBossInstance::OnPlayerExit(Entity *self, Entity *player) {
 | 
			
		||||
    UpdatePlayer(self, player->GetObjectID(), true);
 | 
			
		||||
    //TODO: Add functionality to dynamically turn off the large team variable when enough players leave.
 | 
			
		||||
    GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayerLeft", 0, 0,
 | 
			
		||||
                                         player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS);
 | 
			
		||||
    // Fetch the total players loaded from the vars
 | 
			
		||||
    auto totalPlayersLoaded = self->GetVar<std::vector<LWOOBJID> >(TotalPlayersLoadedVariable);
 | 
			
		||||
    
 | 
			
		||||
    // Find the player to remove
 | 
			
		||||
    auto playerToRemove = std::find(totalPlayersLoaded.begin(), totalPlayersLoaded.end(), player->GetObjectID());
 | 
			
		||||
 | 
			
		||||
    // If we found the player remove them from out list of players
 | 
			
		||||
    if (playerToRemove != totalPlayersLoaded.end()) {
 | 
			
		||||
        totalPlayersLoaded.erase(playerToRemove);
 | 
			
		||||
    } else {
 | 
			
		||||
        Game::logger->Log("NjMonastryBossInstance", "Failed to remove player at exit.\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Set the players loaded var back
 | 
			
		||||
    self->SetVar<std::vector<LWOOBJID>>(TotalPlayersLoadedVariable, totalPlayersLoaded);
 | 
			
		||||
 | 
			
		||||
    // Since this is an exit method, check if enough players have left.  If enough have left
 | 
			
		||||
    // resize the instance to account for such.
 | 
			
		||||
    if (totalPlayersLoaded.size() <= 2) self->SetVar<bool>(LargeTeamVariable, false);
 | 
			
		||||
 | 
			
		||||
    GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayerLeft", 0, 0, player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NjMonastryBossInstance::OnActivityTimerDone(Entity *self, const std::string &name) {
 | 
			
		||||
 
 | 
			
		||||
@@ -144,8 +144,9 @@ void SGCannon::OnMessageBoxResponse(Entity *self, Entity *sender, int32_t button
 | 
			
		||||
    if (player != nullptr) {
 | 
			
		||||
        if (button == 1 && identifier == u"Shooting_Gallery_Stop")
 | 
			
		||||
        {
 | 
			
		||||
            static_cast<Player*>(player)->SendToZone(1300);
 | 
			
		||||
 | 
			
		||||
            UpdatePlayer(self, player->GetObjectID(), true);
 | 
			
		||||
            RemovePlayer(player->GetObjectID());
 | 
			
		||||
            StopGame(self, true);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user