Exemple #1
0
/**
 @brief pCenter(or vCenter)를 중심으로 radius범위내의 유닛들을 얻어 어레이에 담는다.
 @return 얻어낸 타겟수
 @param pCenter 중심타겟. null이면 vCenter를 사용한다.
 @param vCenter 중심좌표. pCenter가 있다면 사용되지 않는다.
 @param pixelRadius 픽셀단위 반지름.
 @param bitSideFilter 검색해야할 진영
 @param numCost 총 코스트값. 각 유닛은 크기 코스트가 있으며 타겟이 검색될때마다 numCost에서 차감한다. 0이되면 더이상 담지 않는다. 차감한 코스값이 마이너스가 될수는 없다.
                0은 코스트에 관계없이 무조건 타겟1개만 검색. -1은 무효값. 
 @param bIncludeCenter 중심타겟(pCenter가 있을경우)을 대상에 포함할지 말지. pCenter가 없다면 이 옵션은 무시된다.
*/
int XEObjMngWithType::GetListUnitRadius2( XVector<XSPUnit> *pOutAry,
																					XEBaseWorldObj *pCenter,
																					const XE::VEC2& vCenter,
																					float pixelRadius,
																					BIT bitSideFilter,
																					int numCost,
																					bool bIncludeCenter,
																					BIT bitFlag ) const		// 생존필터  
{
	if( numCost < 0 )
		return 0;
	//
	XVector<XSPUnit> aryInNew;				// pOutAry에 이미 타겟이 있는채로 들어왔을때 그것은 제한 리스트
	XVector<XSPUnit> aryIn = *pOutAry;	// 기존타겟에 반경검사타겟까지 포함.
	int costSum = 0;
	for( auto spUnit : m_listUnits ) {
		if( spUnit->IsDestroy() )
			continue;
		XBREAK( spUnit == nullptr );
		if( (spUnit->GetCamp() & bitSideFilter) == 0 )
			continue;
		if( (bitFlag & XSKILL::xTF_LIVE) == 0 && spUnit->IsLive() )
			continue;
		if( (bitFlag & XSKILL::xTF_DEAD) == 0 && spUnit->IsDead() )
			continue;
		// 시전대상을 포함하지 않는 조건일때 유닛이 시전대상이면 스킵
		if( pCenter
				&& pCenter->GetsnObj() == spUnit->GetsnObj()		// spUnit이 중심타겟일때
				&& bIncludeCenter == false )										// 중심타겟안포함 옵션이면 스킵한다.
			continue;
		if( bitFlag & XSKILL::xTF_DIFF_SQUAD ) {
			// spUnit이 이미 찾은 유닛과 같은 부대면 스킵
			bool bExisted = false;
			for( auto& spFinded : aryIn ) {
				if( spUnit->GetpSquadObj()->GetsnSquadObj() == spFinded->GetpSquadObj()->GetsnSquadObj() ) {
					bExisted = true;
					break;
				}
			}
			if( bExisted )
				continue;
		}
		const XE::VEC2 vDist = spUnit->GetvwPos().ToVec2() - vCenter;
		const float distsq = vDist.Lengthsq();
		// 코스트와 관계없이 일단 범위안에 들어가는 타겟은 모두 담은후 거기서 다시 코스트에 따라 랜덤으로 꺼낸다.
		if( distsq <= pixelRadius * pixelRadius ) {
			aryIn.Add( spUnit );
			aryInNew.Add( spUnit );
			costSum += spUnit->GetSizeCost();		// 배열에 들어간 유닛들의 토탈코스트
		} // in radius
	} // for
	// 목표코스트를 다 채우지 못했거나 딱맞게 채웠을때는 전체 리스트에서 랜덤으로 뽑을필요가 없으므로 그냥 검색된 리스트를 모두 리턴한다.
	if( costSum <= numCost ) {
		*pOutAry = aryIn;
		return pOutAry->Size();
	}
	int currCost = numCost;
// 	XVector<XSPUnit> ary = *pOutAry;
// 	pOutAry->Clear();
	// 영역안에 들어온 타겟들을 대상으로 다시 코스트에 따라 실제 타겟을 선정한다.
	while( aryInNew.Size() > 0 ) {
		auto spUnit = aryInNew.PopFromRandom();
		if( numCost == 0 ) {
			if( pOutAry->Size() == 0 )
				pOutAry->Add( spUnit );
			return 1;
		} else {
			const auto costUnit = spUnit->GetSizeCost();
			if( costUnit <= currCost ) {
				// 유닛 코스트가 남은 코스트를 깔수 있을때만.
				currCost -= costUnit;
				XBREAK( currCost < 0 );
				pOutAry->Add( spUnit );
				if( currCost == 0 )				// 코스트를 다 채웠으면 리턴.
					return pOutAry->Size();
			}
		}
	}
	return pOutAry->size();
}
Exemple #2
0
/**
 full_list.txt를 만든다.
 core_list.txt를 만든다.(apk50메가선을 유지하도록)
*/
void XMain::DoExtract( void )
{
    // 일단 모든 리소스 파일의 목록을 뽑는다.
//	XArrayLinear<XSYSTEM::XFILE_INFO> aryAll;
    XVector<XSYSTEM::XFILE_INFO> aryAll;
//	XSYSTEM::CreateFileList( XE::_GetPathPackageRoot(), _T("*.*"), &aryAll );
    XSYSTEM::GetFileList( XE::_GetPathPackageRoot(), _T("*.*"), &aryAll, _T("") );
    if( aryAll.Size() > 1500 ) {

    }
    // full_list.txt를 만든다.
    {
// 		XArrayLinear<XPatch::XRES_INFO> ary;
// 		ary.Create( aryAll.size() );
        XVector<XPatch::XRES_INFO> ary;
        int cnt = 1;
        // 파일별로 체크섬을 뽑아 둔다.
//		XARRAYLINEAR_LOOP( aryAll, XSYSTEM::XFILE_INFO, info )
        for( auto& info : aryAll ) {
            XPatch::XRES_INFO resInfo;
            resInfo.strFile = info.strFile;
            resInfo.size = info.size;
            resInfo.llChecksum = XE::CalcCheckSum( info.strFile.c_str() );
            _tstring strFilename = XE::GetFileName( resInfo.strFile.c_str() );
            int idxDuplicate = GetResIdxByCheckSum( ary, resInfo.llChecksum );
            if( idxDuplicate != -1 ) {
                XALERT( "duplicate checksum file: idx=%d,%d", idxDuplicate, cnt );
            }
            ary.Add( resInfo );
            CONSOLE( "%d:%s.... %d byte ....checksum=0x%I64x",
                     cnt++,
                     strFilename.c_str(),
                     resInfo.size,
                     resInfo.llChecksum );
        }
        // full_list.txt를 생성한다.
        WriteFullList( ary );
    }
    // core_list.txt를 뽑아낸다.
    {
// 		XArrayLinear<_tstring> aryCore;
// 		aryCore.Create( aryAll.size() );
        XVector<_tstring> aryCore;
        int  i = 0;
//		XARRAYLINEAR_LOOP( aryAll, XSYSTEM::XFILE_INFO, info )
        for( auto& info : aryAll ) {
//			TCHAR szFlename[ 256 ];
//			_tcscpy_s( szFlename, XE::GetFileName( info.strFile.c_str() ) );
            const _tstring strFileName = XE::GetFileName( info.strFile );
            // 테마에 속하지 않는 몬스터중에 mob_ 으로 시작하는 몬스터는
            // 제작은 되었으나 아직 테마에 반영이 안된 몬스터이므로 제외시킨다.
            BOOL bCore = TRUE;
//			TCHAR szExt[ 16 ];
//			_tcscpy_s( szExt, XE::GetFileExt( strFileName ) );
            const _tstring strExt = XE::GetFileExt( strFileName );
            // 다음 단어가 포함되어 있는 파일은 모두 제외
// 			if( _tcsstr( szFlename, _T( "treant" ) ) ||
// 				_tcsstr( szFlename, _T( "rock" ) ) )
// 				bCore = FALSE;
            // 액셀 파일 제외
//			if( XE::IsSame( szExt, _T("xlsx") ) )
            if( strExt == _T("xlsx") )
                bCore = FALSE;
// 			if( XE::IsSame( szFlename, _T("core_list.txt") ) ||
// 				XE::IsSame( szFlename, _T("full_list.txt") ) )
// 				bCore = FALSE;
            if( strFileName == _T("core_list.txt")
                    || strFileName == _T("full_list.txt") )
                bCore = FALSE;
            if( _tcsstr( strFileName.c_str(), _T("sample")) )
                bCore = FALSE;
            //
            if( bCore )
            {
                aryCore.Add( info.strFile );
                XTRACE( "%d: %s", i ++, info.strFile.c_str() );
            } else
            {
                // 제외된 파일명
                XTRACE( "-----------%s", info.strFile.c_str() );
            }

        }
        // core_list.txt로 저장한다.
        WriteCoreList( aryCore );
    }

}
Exemple #3
0
void XEWinSocketSvr::ProcessLoginedList()
{
	XVector<XSPWinConnInServer> aryDestroy;
	auto llMilli1 = GET_FREQ_TIME();
	XPROF_OBJ( "listLogined" );
	auto plistLogined = &m_Logined.m_shoList.GetSharedObj();
	// 동접이 많으면 이 많은 커넥션들 다 패킷펌핑하기전까진 워커스레드 접속스레드 멈춰야 되는데... 이래선 싱글스레드와 다를바 없지 않은가.
	// 로그인된 커넥션들 프로세스
	XINT64 llProcessTotal = 0;
	XINT64 lllock = 0;
//	for( auto spConnect : *plistLogined ) {
	
	XINT64 llStart = XE::GetFreqTime();;
	for( auto itor = (*plistLogined).begin(); itor != (*plistLogined).end(); ) {
		auto spConnect = (*itor);
		auto pConnect = spConnect.get();
		XINT64 lllock1 = XE::GetFreqTime();;
		if( lllock1 - llStart > 100000 )		// 처리속도가 너무 올래걸릴거 같으면 일단 그냥 루프 빠져나감.
			break;
		pConnect->GetspLock()->Lock( __TFUNC__ );
		lllock += GET_FREQ_TIME() - lllock1;
		const int cntUse = spConnect.use_count();
		if( XASSERT( pConnect ) ) {
			if( pConnect->IsDisconnected() ) {
				OnDisconnectConnection( spConnect );
				pConnect->OnDisconnect();
			}
			if( !pConnect->GetbDestroy() ) {
				auto llProcess = GET_FREQ_TIME();
				pConnect->Process();
				llProcessTotal += (GET_FREQ_TIME() - llProcess);
				//
				if( pConnect->IsDisconnected() ) {	// 연결은 끊어졌어도 클라측에서 중요한 패킷을 보냈을수도 있으므로 패킷펌핑은 다 끝내고 삭제하도록 바뀜.
					pConnect->SetbDestroy( true );
				}
				// 커넥션이 비동기 파괴명령을 처리
				pConnect->ProcesssAsyncDisconnect();
			}
			if( pConnect->GetbDestroy() ) {
				++m_numDestroyAdd;
				aryDestroy.Add( spConnect );
				plistLogined->erase( itor++ );
			} else
				++itor;
		}
		pConnect->GetspLock()->Unlock();
	}

	auto llPass = GET_FREQ_TIME() - llMilli1;
	m_aryTime.Add( xProfile(_T("process list"), llPass ) );
	m_aryTime.Add( xProfile(_T("process"), llProcessTotal ) );
	m_aryTime.Add( xProfile( _T( "lock" ), lllock ) );
	m_aryTime.Add( xProfile( _T( "num process" ), plistLogined->size() ) );
	// Logined 프로세스 & destroy
	//////////////////////////////////////////////////////////////////////////
	auto pListConnected = &m_Connected.m_shoList.GetSharedObj();
	m_numConnected = pListConnected->size();		// 멀티스레드이므로 여기에 값이 있을 수 있음.
	if( m_numConnected > m_maxConnected )
		m_maxConnected = m_numConnected;
	m_Connected.m_shoList.ReleaseSharedObj();
	m_numLogined = plistLogined->size();
	if( m_numLogined > m_maxLogined )
		m_maxLogined = m_numLogined;
	// 순간적으로 numConnect수보다 커넥션객체의 생성수가 훨씬 많을때가 있다. 
	// leak으로 보이지만 봇 클라이언트를 종료시키는 순간 모두 사라지는걸로 보아 순간적으로 접속이 몰릴때 메인스레드 프로세스에서
	// 다 처리를 못해서 그런듯 하다.
	// unlock
	m_Logined.m_shoList.ReleaseSharedObj();
	// 삭제예정된 커넥션들 참조해제
	ProcessDestroyList( aryDestroy );
	aryDestroy.clear();
} // process & destroy