diff --git a/src/servers/sapphire_zone/Actor/Player.cpp b/src/servers/sapphire_zone/Actor/Player.cpp index 5319f4d3..0af3d7a5 100644 --- a/src/servers/sapphire_zone/Actor/Player.cpp +++ b/src/servers/sapphire_zone/Actor/Player.cpp @@ -356,17 +356,6 @@ void Core::Entity::Player::returnToHomepoint() void Core::Entity::Player::setZone( uint32_t zoneId ) { - if( !g_territoryMgr.movePlayer( zoneId, getAsPlayer() ) ) - { - // todo: this will require proper handling, for now just return the player to their previous area - m_pos = m_prevPos; - m_rot = m_prevRot; - m_zoneId = m_prevZoneId; - - if( !g_territoryMgr.movePlayer( m_zoneId, getAsPlayer() ) ) - return; - } - sendZonePackets(); } diff --git a/src/servers/sapphire_zone/Actor/PlayerSql.cpp b/src/servers/sapphire_zone/Actor/PlayerSql.cpp index fbf2f60c..22e13f54 100644 --- a/src/servers/sapphire_zone/Actor/PlayerSql.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerSql.cpp @@ -60,7 +60,40 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) m_prevZoneId = res->getUInt( "OTerritoryId" ); m_prevZoneType = res->getUInt( "OTerritoryType" ); - ZonePtr pCurrZone = g_territoryMgr.getZoneByTerriId( zoneId ); + // Position + m_pos.x = res->getFloat( "PosX" ); + m_pos.y = res->getFloat( "PosY" ); + m_pos.z = res->getFloat( "PosZ" ); + setRotation( res->getFloat( "PosR" ) ); + + m_prevPos.x = res->getFloat( "OPosX" ); + m_prevPos.y = res->getFloat( "OPosY" ); + m_prevPos.z = res->getFloat( "OPosZ" ); + m_prevRot = res->getFloat( "OPosR" ); + + ZonePtr pCurrZone = nullptr; + + // if the zone is an instanceContent zone, we need to actually find the instance + if( g_territoryMgr.isInstanceContentTerritory( zoneId ) ) + { + // try to find an instance actually linked to this player + pCurrZone = g_territoryMgr.getLinkedInstance( m_id ); + // if none found, revert to previous zone and position + if( !pCurrZone ) + { + zoneId = m_prevZoneId; + m_pos.x = m_prevPos.x; + m_pos.y = m_prevPos.y; + m_pos.z = m_prevPos.z; + setRotation( m_prevRot ); + pCurrZone = g_territoryMgr.getZoneByTerriId( zoneId ); + } + } + else + { + pCurrZone = g_territoryMgr.getZoneByTerriId( zoneId ); + } + m_zoneId = zoneId; // TODO: logic for instances needs to be added here @@ -86,20 +119,8 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) m_mp = res->getUInt( "Mp" ); m_tp = 0; - // Position - - m_pos.x = res->getFloat( "PosX" ); - m_pos.y = res->getFloat( "PosY" ); - m_pos.z = res->getFloat( "PosZ" ); - setRotation( res->getFloat( "PosR" ) ); - - m_prevPos.x = res->getFloat( "OPosX" ); - m_prevPos.y = res->getFloat( "OPosY" ); - m_prevPos.z = res->getFloat( "OPosZ" ); - m_prevRot = res->getFloat( "OPosR" ); // Model - auto custom = res->getBlobVector( "Customize" ); memcpy( reinterpret_cast< char* >( m_customize ), custom.data(), custom.size() ); @@ -219,6 +240,9 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) if( !m_playerIdToSpawnIdMap.empty() ) m_playerIdToSpawnIdMap.clear(); + if( !g_territoryMgr.movePlayer( pCurrZone, getAsPlayer() ) ) + return false; + return true; } diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp index eab7bddb..13421e94 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp @@ -302,25 +302,7 @@ Core::TerritoryMgr::InstanceIdList Core::TerritoryMgr::getInstanceContentIdList( bool Core::TerritoryMgr::movePlayer( uint32_t territoryId, Core::Entity::PlayerPtr pPlayer ) { auto pZone = getZoneByTerriId( territoryId ); - - if( !pZone ) - { - g_log.error( "Zone " + std::to_string( territoryId ) + " not found on this server." ); - return false; - } - - pPlayer->setTerritoryId( territoryId ); - - // mark character as zoning in progress - pPlayer->setLoadingComplete( false ); - - if( pPlayer->getLastPing() != 0 ) - pPlayer->getCurrentZone()->removeActor( pPlayer ); - - pPlayer->setCurrentZone( pZone ); - pZone->pushActor( pPlayer ); - - return true; + return movePlayer( pZone, pPlayer ); } bool Core::TerritoryMgr::movePlayer( ZonePtr pZone, Core::Entity::PlayerPtr pPlayer ) @@ -342,8 +324,21 @@ bool Core::TerritoryMgr::movePlayer( ZonePtr pZone, Core::Entity::PlayerPtr pPla pPlayer->setCurrentZone( pZone ); pZone->pushActor( pPlayer ); + // map player to instanceId so it can be tracked. + m_playerIdToInstanceMap[pPlayer->getId()] = pZone->getGuId(); + return true; } +Core::ZonePtr Core::TerritoryMgr::getLinkedInstance( uint32_t playerId ) const +{ + auto it = m_playerIdToInstanceMap.find( playerId ); + if( it != m_playerIdToInstanceMap.end() ) + { + return getInstanceZonePtr( it->second ); + } + return nullptr; +} + diff --git a/src/servers/sapphire_zone/Zone/TerritoryMgr.h b/src/servers/sapphire_zone/Zone/TerritoryMgr.h index 1984faca..b7cdcf3c 100644 --- a/src/servers/sapphire_zone/Zone/TerritoryMgr.h +++ b/src/servers/sapphire_zone/Zone/TerritoryMgr.h @@ -109,10 +109,12 @@ namespace Core TODO: Mind multiple instances?! */ ZonePtr getZoneByTerriId( uint32_t territoryId ) const; - bool movePlayer( uint32_t territoryId, Entity::PlayerPtr pPlayer ); bool movePlayer( ZonePtr, Entity::PlayerPtr pPlayer ); + /*! returns an instancePtr if the player is still bound to an isntance */ + ZonePtr getLinkedInstance( uint32_t playerId ) const; + private: using TerritoryTypeDetailCache = std::unordered_map< uint16_t, Data::TerritoryTypePtr >; using InstanceIdToZonePtrMap = std::unordered_map< uint32_t, ZonePtr >; @@ -137,6 +139,9 @@ namespace Core /*! map holding positions for zonelines */ PositionMap m_territoryPositionMap; + /*! map storing playerIds to instanceIds, used for instanceContent */ + PlayerIdToInstanceIdMap m_playerIdToInstanceMap; + /*! internal counter for instanceIds */ uint32_t m_lastInstanceId;