Files
Leviathan/Server/GameServer/Game/DaemonProc/RoamingManager.cpp
T
2026-06-01 12:46:52 +02:00

254 lines
6.1 KiB
C++

#include "RoamingManager.h"
#include "ChannelManager.h"
#include "DungeonManager.h"
#include <set>
RoamingManager & RoamingManager::Instance()
{
static RoamingManager _instance;
return _instance;
}
RoamingManager::~RoamingManager()
{
// 초기화 되어 있지 않으면(또는 DeInit 되어 있으면) DeInit에서 아무 일도 안 함
DeInit();
}
const bool RoamingManager::RegisterRoamingInfo( const int nID, const StructRoamer::ROAMING_TYPE eType, const int nMoveSpeed, const StructRoamer::HATE_TYPE eHateType, const AR_TIME nRespawnInterval, const int nAttributeFlag, int nInitialX, int ninitialY )
{
if( m_bInitialized )
return false;
THREAD_SYNCHRONIZE( m_RoamerLock );
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( (*it)->GetRoamingID() == nID )
return false;
}
int channel_id = ChannelManager::GetChannelId( nInitialX, ninitialY );
std::vector< unsigned char > vLayers;
int nDungeonID = 0;
if( channel_id )
{
// 레이어가 나뉘는 채널들의 경우 모든 레이어에 모두 StructRoamer를 추가해야 하지만
// 던전의 경우 던전 시즈 레이어에는 추가하면 안 됨
ChannelManager::GetLayersOfChannel( channel_id, vLayers );
nDungeonID = DungeonManager::Instance().GetDungeonID( nInitialX, ninitialY );
if( nDungeonID )
{
std::vector< unsigned char >::iterator itErase = std::find( vLayers.begin(), vLayers.end(), DungeonManager::DUNGEON_SIEGE_LAYER );
if( itErase != vLayers.end() )
{
vLayers.erase( itErase );
}
}
}
else
{
// 일반 필드는 0번 레이어만 추가
vLayers.push_back( 0 );
}
for( std::vector< unsigned char >::iterator lit = vLayers.begin() ; lit != vLayers.end() ; ++lit )
{
unsigned char nLayer = (*lit);
StructRoamer *pRoamer = new StructRoamer( nID, eType, nMoveSpeed, eHateType, nRespawnInterval, nAttributeFlag, nDungeonID && nLayer && nLayer != DungeonManager::DUNGEON_SIEGE_LAYER );
pRoamer->SetCurrentLayer( *lit );
m_vRoamer.push_back( pRoamer );
}
if( nDungeonID )
{
DungeonManager::Instance().RegisterDungeonRoamerInfo( nDungeonID, nID );
}
return true;
}
const bool RoamingManager::UnregisterRoamingInfo( const int nID )
{
if( !m_bInitialized )
return false;
THREAD_SYNCHRONIZE( m_RoamerLock );
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( (*it)->GetRoamingID() == nID )
{
m_vRoamer.erase( it );
return true;
}
}
return false;
}
const bool RoamingManager::RegisterRoamingPointInfo( const int nRoamingID, const int nPosX, const int nPosY )
{
THREAD_SYNCHRONIZE( m_RoamerLock );
bool bSuccess = false;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( (*it)->GetRoamingID() == nRoamingID )
{
(*it)->AddRoamingPoint( ArPosition( nPosX, nPosY ) );
bSuccess = true;
// break; 하지 않고 동일한 ID에 layer만 다른 StructRoamer를 모두 처리해야 함
}
}
return bSuccess;
}
const size_t RoamingManager::GetRoamingPointInfoCount( const int nRoamingID )
{
THREAD_SYNCHRONIZE( m_RoamerLock );
size_t nCount = 0;
// 동일한 RoamingID에 layer 만 다른 경우 중복으로 카운트되지 않도록 하기 위해 체크된 RoamingID를 보관
std::set< int > stCheckedRoamingID;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
int nCurrentRoamerID = (*it)->GetRoamingID();
if( nRoamingID >= 0 )
{
// 특정 StructRoamer의 RoamingPoint 개수만 세는 경우
if( nCurrentRoamerID == nRoamingID )
{
nCount += (*it)->GetRoamingPointCount();
break;
}
}
else
{
// 전체 StructRoamer의 RoamingPoint 개수를 세는 경우
if( stCheckedRoamingID.find( nCurrentRoamerID ) == stCheckedRoamingID.end() )
{
nCount += (*it)->GetRoamingPointCount();
stCheckedRoamingID.insert( nCurrentRoamerID );
}
}
}
return nCount;
}
const bool RoamingManager::AddRoamingCreatureRespawnInfo( const int nRoamingID, const GameContent::ROAMING_CREATURE_RESPAWN_INFO & info )
{
THREAD_SYNCHRONIZE( m_RoamerLock );
bool bSuccess = false;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( (*it)->GetRoamingID() == nRoamingID )
{
(*it)->AddCreatureRespawnInfo( info );
bSuccess = true;
// break; 하지 않고 동일한 ID에 layer만 다른 StructRoamer를 모두 처리해야 함
}
}
return bSuccess;
}
const bool RoamingManager::Init()
{
if( m_bInitialized )
return false;
THREAD_SYNCHRONIZE( m_RoamerLock );
if( m_bInitialized )
return false;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( !(*it)->GetRoamingPointCount() )
{
assert( 0 );
continue;
}
// 던전 레이드용 로밍 객체는 초기화시키지 않음
if( !(*it)->IsInitialized() && !(*it)->IsRaidDungeonRoamer() )
{
(*it)->Init();
}
}
m_bInitialized = true;
return true;
}
const bool RoamingManager::DeInit()
{
if( !m_bInitialized )
return false;
THREAD_SYNCHRONIZE( m_RoamerLock );
if( !m_bInitialized )
return false;
m_bInitialized = false;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
(*it)->DeInit( true );
}
m_vRoamer.clear();
return true;
}
void RoamingManager::InitRoamer( const int nRoamingID, const int nLayer )
{
THREAD_SYNCHRONIZE( m_RoamerLock );
if( !m_bInitialized )
return;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( (*it)->GetRoamingID() == nRoamingID && ( nLayer == -1 || (*it)->GetLayer() == nLayer ) )
(*it)->Init();
}
return;
}
void RoamingManager::DeInitRoamer( const int nRoamingID, const int nLayer )
{
THREAD_SYNCHRONIZE( m_RoamerLock );
if( !m_bInitialized )
return;
for( std::vector< StructRoamer * >::iterator it = m_vRoamer.begin() ; it != m_vRoamer.end() ; ++it )
{
if( (*it)->GetRoamingID() == nRoamingID && ( nLayer == -1 || (*it)->GetLayer() == nLayer ) )
(*it)->DeInit( false );
}
return;
}