1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-24 21:57:44 +00:00
sapphire/src/servers/sapphire_zone/Zone/TerritoryMgr.cpp

357 lines
11 KiB
C++
Raw Normal View History

2018-03-06 22:22:19 +01:00
#include <Logging/Logger.h>
#include <Database/DatabaseDef.h>
#include <Exd/ExdDataGenerated.h>
2018-01-27 23:52:49 +01:00
#include <unordered_map>
2018-01-28 22:36:43 +01:00
#include "Actor/Player.h"
2018-01-27 23:52:49 +01:00
#include "Zone.h"
#include "ZonePosition.h"
#include "InstanceContent.h"
#include "TerritoryMgr.h"
#include "Framework.h"
2018-01-27 23:52:49 +01:00
extern Core::Framework g_fw;
2018-01-27 23:52:49 +01:00
Core::TerritoryMgr::TerritoryMgr() :
m_lastInstanceId( 10000 )
{
}
void Core::TerritoryMgr::loadTerritoryTypeDetailCache()
{
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto idList = pExdData->getTerritoryTypeIdList();
2018-01-27 23:52:49 +01:00
for( auto id : idList )
{
auto teri1 = pExdData->get< Core::Data::TerritoryType >( id );
2018-01-27 23:52:49 +01:00
if( !teri1->name.empty() )
m_territoryTypeDetailCacheMap[id] = teri1;
}
}
bool Core::TerritoryMgr::isValidTerritory( uint32_t territoryTypeId ) const
{
return !( m_territoryTypeDetailCacheMap.find( territoryTypeId ) == m_territoryTypeDetailCacheMap.end() );
}
bool Core::TerritoryMgr::init()
{
loadTerritoryTypeDetailCache();
loadTerritoryPositionMap();
createDefaultTerritories();
return true;
}
uint32_t Core::TerritoryMgr::getNextInstanceId()
{
return ++m_lastInstanceId;
}
Core::Data::TerritoryTypePtr Core::TerritoryMgr::getTerritoryDetail( uint32_t territoryTypeId ) const
{
auto tIt = m_territoryTypeDetailCacheMap.find( territoryTypeId );
if( tIt == m_territoryTypeDetailCacheMap.end() )
return nullptr;
return tIt->second;
}
bool Core::TerritoryMgr::isInstanceContentTerritory( uint32_t territoryTypeId ) const
{
auto pTeri = getTerritoryDetail( territoryTypeId );
if( !pTeri )
return false;
return pTeri->territoryIntendedUse == TerritoryIntendedUse::AllianceRaid ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::BeforeTrialDung ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::Trial ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::Dungeon ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorldInstanceBattle ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::PalaceOfTheDead ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::RaidFights ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::Raids ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::TreasureMapInstance;
2018-01-27 23:52:49 +01:00
}
bool Core::TerritoryMgr::isPrivateTerritory( uint32_t territoryTypeId ) const
{
auto pTeri = getTerritoryDetail( territoryTypeId );
if( !pTeri )
return false;
return pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::HousingPrivateArea ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::JailArea ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::MSQPrivateArea;
}
bool Core::TerritoryMgr::createDefaultTerritories()
{
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto pLog = g_fw.get< Logger >();
2018-01-27 23:52:49 +01:00
// for each entry in territoryTypeExd, check if it is a normal and if so, add the zone object
for( const auto& territory : m_territoryTypeDetailCacheMap )
{
auto territoryId = territory.first;
auto territoryInfo = territory.second;
// if the zone has no name set
if( territoryInfo->name.empty() )
continue;
auto pPlaceName = pExdData->get< Core::Data::PlaceName >( territoryInfo->placeName );
2018-01-27 23:52:49 +01:00
if( !pPlaceName || pPlaceName->name.empty() || !isDefaultTerritory( territoryId ) )
continue;
uint32_t guid = getNextInstanceId();
pLog->info( std::to_string( territoryId ) +
"\t" + std::to_string( guid ) +
"\t" + std::to_string( territoryInfo->territoryIntendedUse ) +
"\t" + ( territoryInfo->name.length() <= 4 ? territoryInfo->name + "\t" : territoryInfo->name ) +
"\t" + ( isPrivateTerritory( territoryId ) ? "PRIVATE" : "PUBLIC" ) +
"\t" + pPlaceName->name );
2018-01-27 23:52:49 +01:00
auto pZone = make_Zone( territoryId, guid, territoryInfo->name, pPlaceName->name );
2018-01-27 23:52:49 +01:00
pZone->init();
InstanceIdToZonePtrMap instanceMap;
instanceMap[guid] = pZone;
m_instanceIdToZonePtrMap[guid] = pZone;
2018-01-27 23:52:49 +01:00
m_territoryInstanceMap[territoryId] = instanceMap;
m_zoneSet.insert( { pZone } );
2018-01-27 23:52:49 +01:00
}
return true;
}
Core::ZonePtr Core::TerritoryMgr::createTerritoryInstance( uint32_t territoryTypeId )
{
if( !isValidTerritory( territoryTypeId ) )
return nullptr;
if( isInstanceContentTerritory( territoryTypeId ) )
return nullptr;
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto pLog = g_fw.get< Logger >();
auto pTeri = getTerritoryDetail( territoryTypeId );
auto pPlaceName = pExdData->get< Core::Data::PlaceName >( pTeri->placeName );
if( !pTeri || !pPlaceName )
return nullptr;
pLog->debug( "Starting instance for territory: " + std::to_string( territoryTypeId ) + " (" + pPlaceName->name + ")" );
auto pZone = make_Zone( territoryTypeId, getNextInstanceId(), pTeri->name, pPlaceName->name );
pZone->init();
2018-01-29 00:40:34 +11:00
m_territoryInstanceMap[pZone->getTerritoryId()][pZone->getGuId()] = pZone;
m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone;
2018-01-29 00:40:34 +11:00
return pZone;
}
Core::ZonePtr Core::TerritoryMgr::createInstanceContent( uint32_t instanceContentId )
{
auto pExdData = g_fw.get< Data::ExdDataGenerated >();
auto pInstanceContent = pExdData->get< Core::Data::InstanceContent >( instanceContentId );
if( !pInstanceContent )
return nullptr;
if( !isInstanceContentTerritory( pInstanceContent->territoryType ) )
return nullptr;
auto pTeri = getTerritoryDetail( pInstanceContent->territoryType );
if( !pTeri || pInstanceContent->name.empty() )
return nullptr;
auto pLog = g_fw.get< Logger >();
pLog->debug( "Starting instance for InstanceContent id: " + std::to_string( instanceContentId ) +
" (" + pInstanceContent->name + ")" );
auto pZone = make_InstanceContent( pInstanceContent, getNextInstanceId(),
pTeri->name, pInstanceContent->name, instanceContentId );
pZone->init();
m_instanceContentToInstanceMap[instanceContentId][pZone->getGuId()] = pZone;
m_instanceIdToZonePtrMap[pZone->getGuId()] = pZone;
m_instanceZoneSet.insert( pZone );
return pZone;
}
bool Core::TerritoryMgr::removeTerritoryInstance( uint32_t instanceId )
2018-01-29 00:52:11 +11:00
{
2018-01-29 20:40:32 +11:00
ZonePtr pZone;
if( ( pZone = getInstanceZonePtr( instanceId ) ) == nullptr )
2018-01-29 00:52:11 +11:00
return false;
2018-01-29 20:40:32 +11:00
m_instanceIdToZonePtrMap.erase( pZone->getGuId() );
if( m_instanceZoneSet.count( pZone ) )
m_instanceZoneSet.erase( pZone );
2018-01-29 20:40:32 +11:00
if( isInstanceContentTerritory( pZone->getTerritoryId() ) )
{
auto instance = boost::dynamic_pointer_cast< InstanceContent >( pZone );
m_instanceContentToInstanceMap[instance->getInstanceContentId()].erase( pZone->getGuId() );
}
else
m_territoryInstanceMap[pZone->getTerritoryId()].erase( pZone->getGuId() );
2018-01-29 00:52:11 +11:00
return true;
}
Core::ZonePtr Core::TerritoryMgr::getInstanceZonePtr( uint32_t instanceId ) const
{
2018-01-29 00:40:34 +11:00
auto it = m_instanceIdToZonePtrMap.find( instanceId );
if( it == m_instanceIdToZonePtrMap.end() )
return nullptr;
2018-01-29 00:40:34 +11:00
return it->second;
}
2018-01-27 23:52:49 +01:00
void Core::TerritoryMgr::loadTerritoryPositionMap()
{
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto pQR = pDb->query( "SELECT id, target_zone_id, pos_x, pos_y, pos_z, pos_o, radius FROM zonepositions;" );
2018-01-27 23:52:49 +01:00
while( pQR->next() )
{
uint32_t id = pQR->getUInt( 1 );
uint32_t targetZoneId = pQR->getUInt( 2 );
Common::FFXIVARR_POSITION3 pos{};
pos.x = pQR->getFloat( 3 );
pos.y = pQR->getFloat( 4 );
pos.z = pQR->getFloat( 5 );
float posO = pQR->getFloat( 6 );
uint32_t radius = pQR->getUInt( 7 );
m_territoryPositionMap[id] = make_ZonePosition( id, targetZoneId, pos, radius, posO );
2018-01-27 23:52:49 +01:00
}
}
bool Core::TerritoryMgr::isDefaultTerritory( uint32_t territoryTypeId ) const
{
auto pTeri = getTerritoryDetail( territoryTypeId );
if( !pTeri )
return false;
return pTeri->territoryIntendedUse == TerritoryIntendedUse::Inn ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::Town ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::OpenWorld ||
pTeri->territoryIntendedUse == TerritoryIntendedUse::OpeningArea;
}
Core::ZonePositionPtr Core::TerritoryMgr::getTerritoryPosition( uint32_t territoryPositionId ) const
{
auto it = m_territoryPositionMap.find( territoryPositionId );
if( it != m_territoryPositionMap.end() )
return it->second;
return nullptr;
}
Core::ZonePtr Core::TerritoryMgr::getZoneByTerriId( uint32_t territoryId ) const
{
auto zoneMap = m_territoryInstanceMap.find( territoryId );
if( zoneMap == m_territoryInstanceMap.end() )
return nullptr;
// TODO: actually select the proper one
return zoneMap->second.begin()->second;
}
void Core::TerritoryMgr::updateTerritoryInstances( uint32_t currentTime )
{
for( auto& zone : m_zoneSet )
2018-01-27 23:52:49 +01:00
{
zone->update( currentTime );
2018-01-27 23:52:49 +01:00
}
for( auto& zone : m_instanceZoneSet )
{
zone->update( currentTime );
}
}
Core::TerritoryMgr::InstanceIdList Core::TerritoryMgr::getInstanceContentIdList( uint16_t instanceContentId ) const
{
std::vector< uint32_t > idList;
auto zoneMap = m_instanceContentToInstanceMap.find( instanceContentId );
if( zoneMap == m_instanceContentToInstanceMap.end() )
return idList;
for( auto& entry : zoneMap->second )
{
idList.push_back( entry.first );
}
2018-01-27 23:52:49 +01:00
return idList;
2018-01-27 23:52:49 +01:00
}
2018-01-28 22:36:43 +01:00
bool Core::TerritoryMgr::movePlayer( uint32_t territoryId, Core::Entity::PlayerPtr pPlayer )
{
auto pZone = getZoneByTerriId( territoryId );
return movePlayer( pZone, pPlayer );
2018-01-28 22:36:43 +01:00
}
bool Core::TerritoryMgr::movePlayer( ZonePtr pZone, Core::Entity::PlayerPtr pPlayer )
{
auto pLog = g_fw.get< Logger >();
2018-01-28 22:36:43 +01:00
if( !pZone )
{
pLog->error( "Zone not found on this server." );
2018-01-28 22:36:43 +01:00
return false;
}
pPlayer->initSpawnIdQueue();
2018-01-28 22:36:43 +01:00
pPlayer->setTerritoryId( pZone->getTerritoryId() );
// mark character as zoning in progress
pPlayer->setLoadingComplete( false );
if( pPlayer->getLastPing() != 0 )
pPlayer->getCurrentZone()->removeActor( pPlayer );
pPlayer->setCurrentZone( pZone );
pZone->pushActor( pPlayer );
// map player to instanceId so it can be tracked.
m_playerIdToInstanceMap[pPlayer->getId()] = pZone->getGuId();
2018-01-28 22:36:43 +01:00
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;
}
2018-01-27 23:52:49 +01:00