/** 압축된 메모리 pSrc(크기sizeSrc)를 풀어서 ppOutDst(크기sizeDst) 에 푼다. */ int XSYSTEM::UnCompressMem( BYTE **ppOutDst, DWORD sizeDst, BYTE *pSrc, DWORD sizeSrc ) { *ppOutDst = NULL; if( XBREAK( sizeDst == 0 ) ) return 0; if( XBREAK( sizeSrc == 0 ) ) return 0; // 압축이 풀릴 메모리 BYTE *pDst = new BYTE[ sizeDst ]; *ppOutDst = pDst; DWORD sizeOutDst = sizeDst; int result = uncompress( (Bytef*)pDst, (uLongf*)&sizeOutDst, (const Bytef*)pSrc, (uLong) sizeSrc ); if( result == Z_OK ) { XBREAK( sizeDst != sizeOutDst ); return 1; } else if( result == Z_MEM_ERROR ) XBREAKF(1, "not enough memory for uncompress"); else if( result == Z_BUF_ERROR ) XBREAKF(1, "dest not enough memory for compress"); else if( result == Z_DATA_ERROR ) XBREAKF(1, "error compress data"); else XBREAKF(1, "unknown uncompress error:%d", result); return 0; }
/** @brief 보정 파라메터의 값을 보정한다. */ int XSkillReceiver::ApplyEffectAdjParam( XSkillDat *pSkillDat, XSkillUser *pCaster, const EFFECT *pEffect, int level, XBuffObj *pBuffObj ) { if( pEffect->invokeParameter <= 0 || pEffect->invokeParameter >= XGAME::xMAX_PARAM ) return 0; XBREAKF( IsAdjParam( pEffect->invokeParameter ) < 0, "처리하지 못한 비보정파라메터(%d)가 있습니다.", pEffect->invokeParameter ); if( pEffect->invokeAbilityMin.size() == 1 ) level = 0; float ability = pEffect->invokeAbilityMin[ level ]; // 능력치값을 다른 다른형태로 변형해서 사용하고 싶다면 아래 핸들러를 정의해서 바꾼다. pCaster->OnAdjustEffectAbility( pSkillDat, pEffect, pEffect->invokeParameter, &ability ); XBREAK( pBuffObj == nullptr ); if( pBuffObj && pBuffObj->IsFirstProcess() ) { OnApplyEffectAdjParam( pCaster, pSkillDat, pEffect, ability ); } AddAdjParamMsg( pEffect->invokeParameter , pEffect->valtypeInvokeAbility , ability ); // return 1; }
void XWndSprObj::CreateSprObj( LPCTSTR szSpr, ID idAct, bool bUseAtlas, bool bBatch, bool bAsyncLoad, xRPT_TYPE loopType ) { if( XE::IsEmpty( szSpr ) ) { SetbDestroy( true ); return; } m_pSprObj = new XSprObj( szSpr, XE::xHSL(), idAct, xRPT_LOOP, bUseAtlas, bBatch, bAsyncLoad, [this, szSpr, idAct]( XSprObj* pSprObj ) { XBREAKF( pSprObj->GetpObjActCurr() == nullptr, "%s, id=%d", szSpr, idAct ); if( pSprObj->GetpObjActCurr() ) { // 캐시에 있다가 불려온것이면 데이타가 있다. const XE::VEC2 vSize = pSprObj->GetSize(); SetSizeLocal( vSize ); SetbUpdate( true ); } else { const XE::VEC2 vSize( 2, 2 ); // 비동기로 로딩해서 크기를 일단 이렇게 맞춤. SetSizeLocal( vSize ); SetbUpdate( true ); } } ); m_pSprObj->SetAction( idAct, loopType ); m_idAct = idAct; m_loopType = loopType; if( m_pSprObj->IsError() ) return; m_strSpr = szSpr; }
/** @brief XML 노드로부터 reward를 읽어들인다. */ bool xRES_NUM::LoadFromXML( XEXmlNode& node, LPCTSTR szTag ) { bool bRet = true; int idx = 0; XEXmlAttr attr = node.GetFirstAttribute(); while( !attr.IsEmpty() ) { if( attr.GetcstrName() == "resource" || attr.GetcstrName() == "res" || attr.GetcstrName() == "type" ) { if( CONSTANT->IsFound() ) { type = (xtResource)sReadResourceConst( attr, szTag ); } else bRet = false; } else if( attr.GetcstrName() == "num" ) { num = attr.GetFloat(); } else { XBREAKF( 1, "%s:알수없는 속성이름. %s", szTag, attr.GetstrName().c_str() ); bRet = false; } // attr = attr.GetNext(); } return bRet; }
XSPBaseLayer XBaseLayer::sCreate( xSpr::xtLayer type ) { XSPBaseLayer spBaseLayer; switch( type ) { case xSpr::xLT_IMAGE: spBaseLayer = xSPLayerImage( new XLayerImage ); break; case xSpr::xLT_OBJECT: spBaseLayer = XSPLayerObject( new XLayerObject ); break; case xSpr::xLT_SOUND: spBaseLayer = XSPLayerSound( new XLayerSound ); break; case xSpr::xLT_EVENT: spBaseLayer = XSPLayerEvent( new XLayerEvent ); break; case xSpr::xLT_DUMMY: spBaseLayer = XSPLayerDummy( new XLayerDummy ); break; default: XBREAKF( 1, "알수없는 레이어 타입:type=%d", type ); break; } if( spBaseLayer ) spBaseLayer->OnCreate(); return spBaseLayer; }
/** 비동기로 recv를 시킴 다수의 워커스레드로부터 호출됨. */ void XEWinConnectionInServer::tWSARecv( void ) { // do { unsigned long readbytes; // 비동기로 전송처리, 큐에 올라감. 이걸해야 스레드에서 데이타가 받아짐. #ifdef _USING_WSA WSABUF b[1]; unsigned long flags = 0; memset( &m_opRecv, 0, sizeof(m_opRecv) ); m_opRecv.typeEvent = 2; b[0].buf = (CHAR *)m_Buffer; b[0].len = sizeof(m_Buffer); if( WSARecv( m_Socket, b, 1, &readbytes, &flags, &m_opRecv, NULL ) == SOCKET_ERROR ) #else // 최초 accept시에는 아래처림 == FALSE로 검사하면 안됨. 원래 0나옴 if( ReadFile( (HANDLE)m_Socket, m_Buffer, sizeof(m_Buffer), &readbytes, &m_op ) == FALSE ) #endif { const auto lastErr = GetLastError(); XBREAKF( lastErr != WSAECONNRESET && lastErr != ERROR_IO_PENDING , "WSARecv error:err=%d", lastErr ); if( lastErr != WSAECONNRESET // 접속끊김 && lastErr != ERROR_IO_PENDING ) { // IO처리중 CONSOLE( "WSARecv error: socket=%x, error=%d", m_Socket, lastErr ); ClearConnection(); } } } while(0); // return; }
void show_error( const char *str ) { #ifdef _XTOOL CONSOLE( "lua error: %s", Convert_char_To_TCHAR( str ) ); #else XBREAKF(1, "lua error: %s", Convert_char_To_TCHAR( str ) ); #endif }
bool XGlobalVal::OnDidFinishLoad() { XTRACE( "loaded global.xml" ); // 루트노드를 구해놓는다. m_pRoot = GetDoc().FirstChild( "global" ); m_nodeRoot.SetpRoot( m_pRoot->ToElement() ); XBREAKF( m_pRoot == NULL, "global node not found" ); return true; }
BOOL XLoginInfo::Save( void ) { FILE *fp = NULL; XBREAK( m_strLoginFile.empty() ); // fprintf_s때문에 euckr형으로 만들어야 함 LPCTSTR _szPath = XE::MakeDocFullPath( _T(""), m_strLoginFile.c_str() ); string strPath = SZ2C( _szPath ); fopen_s( &fp, strPath.c_str(), "wt" ); if( fp == NULL ) { XLOGXN("save failed %s", _szPath ); return FALSE; } #if defined(_XUNIVERSAL) || defined(_XINDONESIA) if( m_typeLogin == xLT_UUID ) { XBREAK( m_strUUID.empty() == true ); fprintf_s( fp, "__uuid\r\n" ); fprintf_s( fp, "\"%s\"\r\n", m_strUUID.c_str() ); XLOGXN("save uuid=%s", C2SZ(m_strUUID.c_str()) ); } else #endif #ifdef _XUNIVERSAL if( m_typeLogin == xLT_IDPW ) { // 아니면 아이디/비번으로 로그인한것. fprintf_s( fp, "__idpw\r\n" ); fprintf_s( fp, "\"%s\"\r\n", m_strID.c_str() ); XLOGXN("id=%s", C2SZ(m_strID.c_str()) ); fprintf_s( fp, "\"%s\"\r\n", m_strPassword.c_str() ); XLOGXN("pw=%s", C2SZ(m_strPassword.c_str()) ); } else #endif #ifdef _XLOGIN_FACEBOOK if( m_typeLogin == xLT_FACEBOOK ) { // 페북으로 로그인한것 fprintf_s( fp, "__facebook\r\n" ); fprintf_s( fp, "\"%s\"\r\n", m_strFbUserId.c_str() ); XLOGXN("save fb id=%s", C2SZ(m_strFbUserId.c_str()) ); fprintf_s( fp, "\"%s\"\r\n", SZ2C(m_strFbUsername.c_str()) ); XLOGXN("save fb username=%s", m_strFbUsername.c_str() ); fprintf_s( fp, "\"%s\"\r\n", SZ2C(m_strFbName.c_str()) ); XLOGXN("save fb name=%s", m_strFbName.c_str() ); } else #endif { fprintf_s( fp, "__none\r\n" ); XBREAKF(1, "unknown m_typeLogin save" ); } fclose( fp ); XLOGXN("loginInfo save success %s", _szPath ); return TRUE; }
void XArrayLinear<T>::operator=( XArrayLinearN<T, N>& ary ) { XBREAKF( m_pArray != NULL, "XArrayLinear is not empty" ); Init(); if( ary.size() == 0 ) return; Create( ary.size() ); int num = ary.size(); for( int i = 0; i < num; ++i ) { Add( ary[ i ] ); } }
XOrderCamera::XOrderCamera( XSeq *pSeq, int idxOrder ) : XOrder( pSeq, idxOrder ) { Init(); m_spProp = std::static_pointer_cast<XPropCamera>( pSeq->GetspProp()->m_aryOrder[ idxOrder ] ); if( SCENE_WORLD ) { if( m_spProp->m_bPopPos ) { // 좌표 pop mode if( XASSERT(!s_stackPos.empty()) ) { // 좌표 복구. const XE::VEC2 vwCamera = s_stackPos.top(); s_stackPos.pop(); SCENE_WORLD->DoMovePosInWorld( vwCamera ); } } else { if( m_spProp->m_bPushPos ) { // 좌표 백업 s_stackPos.push( SCENE_WORLD->GetvwCamera() ); } // 지정된 좌표로 이동 if( m_spProp->m_aryIdsTarget.size() ) { // 카메라에서는 idsTarget을 하나만 쓴다. auto idsTarget = m_spProp->m_aryIdsTarget[0]; auto pWnd = GAME->Find( idsTarget ); if( pWnd ) { auto vPos = pWnd->GetPosLocal(); SCENE_WORLD->DoMovePosInWorld( vPos, 0.5f ); } else { XBREAKF( 1, "%s not found", C2SZ(idsTarget) ); } } else { SCENE_WORLD->DoMovePosInWorld( m_spProp->m_vwDst, 0.5f ); } } } else if( SCENE_BATTLE ) { if( m_spProp->m_bPopPos ) { if( XASSERT( !s_stackPos.empty() ) ) { SCENE_BATTLE->DoMoveCamera( s_stackPos.top() ); s_stackPos.pop(); } } else { if( m_spProp->m_bPushPos ) { s_stackPos.push( SCENE_BATTLE->GetvwCamera() ); } // 지정된 좌표로 이동 XBREAK( m_spProp->m_vwDst.IsZero() ); SCENE_BATTLE->DoMoveCamera( m_spProp->m_vwDst ); } } }
/** pSrc메모리를 압축해서 pOutDst에 메모리를 할당해 돌려준다. pOutSizeDst는 pOutDst의 사이즈. 1이 리턴되면 성공. 0이 리턴되면 실패. */ int XSYSTEM::CreateCompressMem( BYTE** ppOutDst, DWORD *pOutSizeDst, BYTE *pSrc, DWORD sizeSrc ) { *ppOutDst = NULL; *pOutSizeDst = 0; // Upon entry, destLen is the total size of the destination buffer, // which must be at least 0.1% larger than sourceLen plus 12 bytes. DWORD sizeOutDst = (DWORD)((sizeSrc+12) * 1.001f) + 2; // 스트링으로 쓰일수도 있으므로 +2(wchar)을 해줌. BYTE *pTemp = new BYTE[ sizeOutDst ]; // 압축크기의 최대가능성으로 잡는다. int result = compress( (Bytef*)pTemp, (uLongf*)&sizeOutDst, (const Bytef*)pSrc, (uLong)sizeSrc ); if( result == Z_OK ) { if( XBREAK( sizeOutDst > (DWORD)(sizeSrc * 1.5f) ) ) // 이런경우는 없을껄? return 0; *ppOutDst = new BYTE[ sizeOutDst ]; *pOutSizeDst = sizeOutDst; memcpy_s( *ppOutDst, sizeOutDst, pTemp, sizeOutDst ); SAFE_DELETE_ARRAY( pTemp ); return 1; } else if( result == Z_MEM_ERROR ) { // 메모리가 충분하지 않음. XBREAKF(1, "not enough memory for compress"); } else if( result == Z_BUF_ERROR ) { // 내보낼 버퍼의 크기가 충분하지 않음. XBREAKF(1, "dest not enough memory for compress"); } else { XBREAKF(1, "unknown compress error:%d", result); } SAFE_DELETE_ARRAY( pTemp ); return 0; }
XGameLua::XGameLua( const char *cLua ) { Init(); /* 루아 내부에서 다른루아를 include한다고 해도 어차피 마스터본에는 lua파일은 암호화되어 배포되어 include하지 못한다. 그러므로 사전 컴파일된 루아 바이너리를 쓰는 방법을 찾아봐야 할듯. */ TCHAR szFullPath[ 1024 ]; #ifdef _SERVER _tcscpy_s( szFullPath, XE::_GetPathPackageRoot() ); _tcscat_s( szFullPath, XE::MakePath( DIR_SCRIPTW, _T("") ) ); #else switch( XE::GetLoadType() ) { case XE::xLT_PACKAGE_ONLY: #if defined(WIN32) || defined(_VER_IOS) _tcscpy_s( szFullPath, XE::_GetPathPackageRoot() ); _tcscat_s( szFullPath, XE::MakePath( DIR_SCRIPTW, _T("") ) ); #else XBREAKF(1, "do not use! package only type"); #endif break; case XE::xLT_WORK_FOLDER_ONLY: case XE::xLT_WORK_TO_PACKAGE: case XE::xLT_WORK_TO_PACKAGE_COPY: _tcscpy_s( szFullPath, XE::MakeWorkFullPath( DIR_SCRIPTW, _T("") ) ); break; default: XBREAKF( 1, "unknown loadtype" ); } #endif XLOGXN("lua module path.....%s", szFullPath ); SetModulePath( SZ2C( szFullPath ) ); LoadScript( XE::MakePath( DIR_SCRIPTA, cLua ) ); // RegisterGlobal(); }
// inter타입의 보간함수로 timelerp의 보간값을 계산해서 pfOut에 넣는다. 에러가 나면 0이 리턴된다 BOOL XLayerMove::CalcInterpolation( float *pfOut, float fTimeLerp, XBaseLayer::xtInterpolation inter ) { float fSpeedLerp = 0; if( pfOut ) *pfOut = 0; switch( inter ) { case xLINEAR: fSpeedLerp = XE::xiLinearLerp( fTimeLerp ); break; case xACCEL: fSpeedLerp = XE::xiHigherPowerAccel( fTimeLerp, 1.0f, 0 ); break; case xDEACCEL: fSpeedLerp = XE::xiHigherPowerDeAccel( fTimeLerp, 1.0f, 0 ); break; case xSMOOTH: fSpeedLerp = XE::xiSmoothStep( fTimeLerp, 1.0f, 0 ); break; case xSPLINE: fSpeedLerp = XE::xiCatmullrom( fTimeLerp, -10.0f, 0, 1, 1 ); break; default: XBREAKF( 1, "invalide interpolation type:%d", (int)inter ); return FALSE; } if( pfOut ) *pfOut = fSpeedLerp; return TRUE; }
BOOL XESkillMng::Load( LPCTSTR szXml ) { m_strProp = szXml; // 파일은 utf16이지만 테이블엔 utf8로 보관 m_pTextTable = new XTextTableUTF8; if( m_pTextTable->Load( XE::MakePath( DIR_PROP, _T("text_skill.txt") ) ) == FALSE ) { XLOG( "text_skill.txt load failed!" ); return FALSE; } XXMLDoc doc; if( doc.Load( XE::MakePath( DIR_PROP, szXml ) ) == FALSE ) return FALSE; // 루트노드를 찾는다. TiXmlElement *pRoot = doc.GetDoc().FirstChildElement( "skill" ); XBREAKF( pRoot == NULL, "%s: <skill>root node not found" ); // AddConstant(); // LoadSkill( pRoot, NULL, NULL ); return TRUE; }
/** @brief 접속 대기 스레드 */ void XEWinSocketSvr::AcceptThread() { SOCKADDR_IN addr; int addrlen; SOCKET client; HANDLE hIOCP; while( m_bLoopAccept ) { addrlen = sizeof( addr ); // client = WSAAccept( m_Socket, ( struct sockaddr* )&addr, &addrlen, 0, 0 ); // client = accept( m_Socket, ( struct sockaddr* )&addr, &addrlen ); // 새로운 클라이언트의 접속 // XBREAK( client == INVALID_SOCKET ); // DWORD idThread = GetCurrentThreadId(); int sizeList = 0; if( client != INVALID_SOCKET ) { TCHAR szIPClient[ 64 ]; _stprintf_s( szIPClient, _T( "%d.%d.%d.%d" ), addr.sin_addr.S_un.S_un_b.s_b1, addr.sin_addr.S_un.S_un_b.s_b2, addr.sin_addr.S_un.S_un_b.s_b3, addr.sin_addr.S_un.S_un_b.s_b4 ); CONSOLE_TAG( "connect", "%s:ip=%s", __TFUNC__, szIPClient ); // 이 서버로 접속되는 접속객체 하나 생성. // 만약 이 서버가 월드서버라면 클라이언트 커넥션을 받고 만약 다른 서버와도 커넥션이 있어야 한다면 월드서버쪽에서 그 서버로 접속하여 별도의 커넥션을 유지시킬것 auto spConnect = tCreateConnectionObj( client, szIPClient ); if( spConnect ) { // auto spConnect = std::make_shared<XE::xWinConn>( spConnect ); // Lock: 대기열 리스트의 자원을 점유한다. XAutoSharedObj<XList_Connection> shaListConnected( m_Connected.m_shoList ); XAutoSharedObj<XMap_Connection> shaMapConnected( m_Connected.m_shoMap ); auto plistConnected = shaListConnected.Get(); auto pMapConnected = shaMapConnected.Get(); sizeList = plistConnected->size(); // const ID idConnect = spConnect->GetidConnect(); // 대기열에 올라간순간부터 락이 되어야 하기때문에 미리 락을 걸음. { XAUTO_LOCK3( spConnect ); // 락부터 걸고 #ifdef _DEBUG // 미리 한번 검사해본다. // auto spConnExist = _FindspConnInList( *plistConnected, idConnect ); // auto spConnExistInMap = _FindspConnInMap( *pMapConnected, idConnect ); // if( XASSERT(spConnExist == nullptr && spConnExistInMap == nullptr) ) #endif // _DEBUG { plistConnected->Add( spConnect ); // 대기열에 올림. auto itor = pMapConnected->find( idConnect ); if( itor != pMapConnected->end() ) { XBREAK(1); } (*pMapConnected)[ idConnect ] = spConnect; // IOCP 객체에 클라이언트 소켓을 추가 hIOCP = ::CreateIoCompletionPort( (HANDLE)client , m_hIOCP , (DWORD)spConnect->GetidConnect() , 0 ); XBREAK( hIOCP != m_hIOCP ); // 이런 경우가 있나? BTRACE( "connected:%s", GetszName() ); spConnect->Set_bConnected( TRUE ); // 비동기 recv spConnect->tWSARecv(); // 패킷받을 준비가 된걸 알림 const int cntUse = spConnect.use_count(); spConnect->SetbConnectedFlag( true ); // m_bConnectedFlag = true; // SendConnectComplete실행하도록 한다. // SendConnectComplete( spConnect ); // 여기서 패킷 Crypt하면서 m_pSocketSvr를 참조하게 된다. 스레드안전 주의. } } } else { XBREAKF( 1, "create failed memory pool: CreateConnectionObj" ); // 메모리풀 할당에 실패한경우. closesocket( client ); } } else { m_bLoopAccept = FALSE; } // 갑자기 접속이 몰리면 메인스레드에서 다 소화할때까지 잠시 대기시킨다. // while(sizeList > 100) { // XAutoSharedObj<XList_Connection> shaListConnected( m_Connected.m_shoList ); // auto pList = shaListConnected.Get(); // if( pList->size() < 100 ) // break; // Sleep(1); // } Sleep( m_msecSleepConn ); } m_bExitAccept = TRUE; // 스레드루프에서 빠져나왔음. } // AcceptThread()
_XNoRecursiveInstance::~_XNoRecursiveInstance() { // 아직 해제되지 않은 리커시브방지 객체가 있다. XBREAKF( m_refCnt != 0, "is not release _XNoRecursiveInstance" ); }
BOOL XLoginInfo::Load( LPCTSTR szFile ) { CToken token; m_strLoginFile = szFile; // 플랫폼에 관계없이 이 함수로 대동단결 if( token.LoadFromDoc( szFile, XE::TXT_EUCKR ) == xFAIL ) { XLOGXN("login.txt not found"); return FALSE; } XLOGXN("load login.txt success!"); if( token.GetToken() == NULL ) return FALSE; #ifdef _XLOGIN_UUID if( token == _T("__none") ) { // login파일이 없으면 디폴트 uuid방식으로 로그인 m_typeLogin = xLT_UUID; XLOGXN("uuid not found. create uuid now."); char cUUID[ 48 ]; XPH::GetUUID( cUUID, 48 ); m_strUUID = cUUID; XLOGXN("UUID:%s", C2SZ( cUUID ) ); Save(); } else if( token == _T("__uuid") ) { if( token.GetToken() ) m_strUUID = SZ2C(token.m_Token); else return FALSE; // 파일이 깨진것 앱을 다시 설치해야함. m_typeLogin = xLT_UUID; } else #endif #ifdef _XLOGIN_FACEBOOK if( token == _T("__facebook") ) { if( token.GetToken() ) m_strFbUserId = SZ2C(token.m_Token); else return FALSE; // if( token.GetToken() ) m_strFbUsername = token.m_Token; else { // 페북에 유저네임이 없을수도 있게 되어서 에러로 처리하지 않음. // m_strFbUserId.clear(); // return FALSE; } m_typeLogin = xLT_FACEBOOK; } else #endif #ifdef _XUNIVERSAL if( token == _T("__idpw") ) { // if( token.GetToken() ) m_strID = SZ2C( token.m_Token ); XLOGXN("login id:%s", token.m_Token); // if( token.GetToken() ) m_strPassword = SZ2C( token.m_Token ); else { m_strID.clear(); return FALSE; } m_typeLogin = xLT_IDPW; #ifdef _DEV XLOGXN("login pw:%s", token.m_Token); #endif } else #endif { m_typeLogin = xLT_NONE; XBREAKF( 1, "unknown login identifier:%s", token.m_Token ); return FALSE; } // add facebook login mode ////////////////////////////////////////////////////////////////////////// m_bLoaded = TRUE; return TRUE; }
/* BOOL XBaseProp::LoadBlock( CToken& token, void *pBlockObj, LPCTSTR szBlockName, ID _idBlock ) { TCHAR szLastToken[64]; XCLEAR_ARRAY( szLastToken ); ID idBlock = 0; while(1) { if( token.GetToken() == NULL ) break; if( token == _T("{") ) { #pragma message( "이름 없어도 블럭생성되게 해서 하위계층으로 계속 복사되도록. 스킬처럼" ) // if( szBlockName ) // 블럭네임이 있을때만 블럭을 생성한다. 스크립트에서 최상위 블럭은 보통 이게 널이다 void *pSendBlock = NULL; void *pNewBlock = pSendBlock = CreateNewBlock( szLastToken, idBlock ); if( pNewBlock == NULL ) // 새로 할당 못받은경우는 상위에서 넘겨준 포인터로 넘겨준다. pSendBlock = pBlockObj; if( LoadBlock( token, pSendBlock, szLastToken, idBlock ) == FALSE ) { //XPROP_BREAKF( 1, "%s블럭 읽기실패", szLastToken ); XBREAKF( 1, "%s->%s{ }:\n알수없는 기호 나옴", token.m_strFileName, (szBlockName)? szBlockName : _T("") ); SAFE_DELETE( pNewBlock ); return FALSE; } else { if( pNewBlock ) // 어쨋든 여기서 블럭 할당 못받은경우는 리스트에 추가할수 없다 AddNewBlock( pNewBlock ); } } else if( token == _T("}") ) break; else { // 바로 다음 토큰이 블럭{ 이라면 블럭이름으로 인식 TCHAR szNextToken1[ MAX_TOKEN ]; TCHAR szNextToken2[ MAX_TOKEN ]; token.PushPos(); // 현재 위치 백업 _tcscpy_s( szNextToken1, token.GetToken() ); _tcscpy_s( szNextToken2, token.GetToken() ); // 다음, 다다음 토큰까지 읽어본다 token.PopPos(); // 토큰위치 복구 if( szNextToken1[0] == '{' ) { if( token.IsNumeric( token.m_Token ) ) // { 앞에 있는 토큰이 숫자형태라면 idBlock = token.ToNumber( token.m_Token ); // 일단 idblock으로 가정 else { _tcscpy_s( szLastToken, token.m_Token ); idBlock = 0; } } else if( token.IsNumeric( szNextToken1 ) && szNextToken2[0] == '{' ) // 다음 토큰이 숫자+{ 면 블럭 아이디로 인식 { _tcscpy_s( szLastToken, token.m_Token ); // 일단 블럭이름 받아놓고 idBlock = token.GetNumber(); // block id } else { // 토큰 파싱은 버추얼 파서에게 맞긴다 if( OnParse( token, pBlockObj, szBlockName ) == FALSE ) { XERROR( "%s->%s{ }:\n알수없는 기호 나옴", token.m_strFileName, (szBlockName)? szBlockName : _T("") ); // XPROP_BREAKF( 1, "알수없는 기호나옴: %s", token.m_Token ); // return FALSE; // 알수없는 기호나와도 일단 계속 읽게 하자 } } } } return TRUE; } */ BOOL XBaseProp::LoadBlock( CToken& token, void *pBlockObj, LPCTSTR szBlockName, ID _idBlock ) { TCHAR szLastToken[64]; XCLEAR_ARRAY( szLastToken ); ID idBlock = 0; while(1) { if( token.GetToken() == NULL ) break; if( token == _T("{") ) { #pragma message( "이름 없어도 블럭생성되게 해서 하위계층으로 계속 복사되도록. 스킬처럼" ) // if( szBlockName ) // 블럭네임이 있을때만 블럭을 생성한다. 스크립트에서 최상위 블럭은 보통 이게 널이다 void *pSendBlock = NULL; void *pNewBlock = pSendBlock = CreateNewBlock( szLastToken, idBlock ); if( pNewBlock == NULL ) // 새로 할당 못받은경우는 상위에서 넘겨준 포인터로 넘겨준다. pSendBlock = pBlockObj; if( LoadBlock( token, pSendBlock, szLastToken, idBlock ) == FALSE ) { //XPROP_BREAKF( 1, "%s블럭 읽기실패", szLastToken ); XBREAKF( 1, "%s->%s{ }:\n알수없는 기호 나옴", token.m_strFileName, (szBlockName)? szBlockName : _T("") ); SAFE_DELETE( pNewBlock ); return FALSE; } else { if( pNewBlock ) // 어쨋든 여기서 블럭 할당 못받은경우는 리스트에 추가할수 없다 AddNewBlock( pNewBlock ); } } else if( token == _T("}") ) break; else { // 토큰 파싱은 버추얼 파서에게 맞긴다 if( OnParse( token, pBlockObj, szBlockName ) == FALSE ) { // 토큰해석을 못했다면 블럭 이름일 수 있다. // 바로 다음 토큰이 블럭{ 이라면 블럭이름으로 인식 TCHAR szNextToken1[ MAX_TOKEN ]; TCHAR szNextToken2[ MAX_TOKEN ]; token.PushPos(); // 현재 위치 백업 _tcscpy_s( szNextToken1, token.GetToken() ); if( token.GetToken() == NULL ) break; _tcscpy_s( szNextToken2, token.m_Token ); // 다음, 다다음 토큰까지 읽어본다 token.PopPos(); // 토큰위치 복구 if( szNextToken1[0] == '{' ) { if( token.IsNumeric( token.m_Token ) ) // { 앞에 있는 토큰이 숫자형태라면 idBlock = token.ToNumber( token.m_Token ); // 일단 idblock으로 가정 else { _tcscpy_s( szLastToken, token.m_Token ); idBlock = 0; } } else if( token.IsNumeric( szNextToken1 ) && szNextToken2[0] == '{' ) // 다음 토큰이 숫자+{ 면 블럭 아이디로 인식 { _tcscpy_s( szLastToken, token.m_Token ); // 일단 블럭이름 받아놓고 idBlock = token.GetNumber(); // block id } else { // 토큰 파싱은 버추얼 파서에게 맞긴다 // if( OnParse( token, pBlockObj, szBlockName ) == FALSE ) { // XERROR( "%s->%s{ }:\n알수없는 기호 나옴", token.m_strFileName, (szBlockName)? szBlockName : _T("") ); // } } } } } return TRUE; }
BOOL XShader::LoadShaderFromStr( const GLchar *cVertShader , const GLchar *cFragShader , const char *cszTag ) { GLuint vertShader, fragShader; BOOL bRet = FALSE; do { // Create shader program. m_glProgram = glCreateProgram(); // Create and compile vertex shader. if( !CompileShaderFromString( &vertShader, GL_VERTEX_SHADER, cVertShader, cszTag ) ) { XBREAKF( 1, "Failed to compile vertex shader" ); bRet = FALSE; break; } // Create and compile fragment shader. if( !CompileShaderFromString( &fragShader, GL_FRAGMENT_SHADER, cFragShader, cszTag ) ) { XBREAKF( 1, "Failed to compile fragment shader" ); bRet = FALSE; break; } // Attach vertex shader to program. glAttachShader( m_glProgram, vertShader ); // Attach fragment shader to program. glAttachShader( m_glProgram, fragShader ); // Bind attribute locations. // This needs to be done prior to linking. glBindAttribLocation( m_glProgram, XE::ATTRIB_POS, "position" ); glBindAttribLocation( m_glProgram, XE::ATTRIB_TEXTURE, "texture" ); glBindAttribLocation( m_glProgram, XE::ATTRIB_COLOR, "color" ); glBindAttribLocation( m_glProgram, XE::ATTRIB_SIZE, "size" ); // Link program. if( !LinkShader( m_glProgram, cszTag ) ) { XTRACE( "Failed to link program: %d %s", m_glProgram, C2SZ(cszTag) ); if( vertShader ) { glDeleteShader( vertShader ); vertShader = 0; } if( fragShader ) { glDeleteShader( fragShader ); fragShader = 0; } if( m_glProgram ) { glDeleteProgram( m_glProgram ); m_glProgram = 0; } bRet = FALSE; break; } // Get uniform locations. // 세이더내 유저변수의 로케이션값을 받아둔다. 이 변수에다 값을 쓰려면 이 로케이션 값을 이용해야 한다. m_locUniforms[UNIFORM_MVP_MATRIX] = glGetUniformLocation( m_glProgram, "mMVP" ); m_locUniforms[UNIFORM_COLOR] = glGetUniformLocation( m_glProgram, "col" ); m_locUniforms[UNIFORM_FLOAT] = glGetUniformLocation( m_glProgram, "value" ); // m_locUniforms[UNIFORM_MODEL_MATRIX] = glGetUniformLocation(m_glProgram, "worldMatrix"); // Release vertex and fragment shaders. if( vertShader ) { glDetachShader( m_glProgram, vertShader ); glDeleteShader( vertShader ); } if( fragShader ) { glDetachShader( m_glProgram, fragShader ); glDeleteShader( fragShader ); } bRet = TRUE; } while( 0 ); // if( bRet ) // BTRACE("success."); // else // XTRACE("failed."); return bRet; }
/** @brief 시전대상(혹은 시전좌표)를 기준으로 발동대상(혹은 발동좌표)을 얻는다. this는 시전자 */ int XSkillUser::GetInvokeTarget( XVector<XSkillReceiver*> *_plistOutInvokeTarget, // 결과를 이곳에 받습니다 XE::VEC2* pOutIvkTarget, // 발동대상이 좌표형일경우 좌표가 담긴다. const XSkillDat *pDat, int level, xtInvokeTarget typeIvkTarget, // 발동대상 const EFFECT *pEffect, // 효과. XSkillReceiver *pCastTarget, // 시전대상 const XE::VEC2& vCastTarget ) // 시전대상이 좌표형일때 { // 좌표에 값이 있으면 타겟은 널이어야 한다., XBREAK( vCastTarget.IsNotZero() && pCastTarget != nullptr ); XBREAK( pCastTarget == nullptr && vCastTarget.IsZero() ); // virtual. typeIvkTarget을 하위클래스에서 가공하기 위한 땜빵. typeIvkTarget = pCastTarget->OnGetInvokeTarget( pDat, pEffect, typeIvkTarget ); // auto& aryTempInvokes = *_plistOutInvokeTarget; xtFriendshipFilt filtIvkFriendship = pEffect->invokefiltFriendship; if( filtIvkFriendship == xfNONESHIP ) filtIvkFriendship = pEffect->castfiltFriendship; XBREAK( filtIvkFriendship == xfNONESHIP ); // switch( typeIvkTarget ) { // 시전대상 case xIVT_CAST_TARGET: #pragma message("==========================피격자라는 발동대상이 필요하나?") case xIVT_ATTACKED_TARGET: // 피격자. 이때는 pCastingTarget이 피격자가 된다. #pragma message("==========================IsInvokeAble 이거 꼭 필요함?") if( pCastTarget ) { if( IsInvokeAble( pDat, pCastTarget, pEffect ) ) aryTempInvokes.push_back( pCastTarget ); } else { *pOutIvkTarget = vCastTarget; } break; case xIVT_CAST_TARGET_RADIUS: case xIVT_CAST_TARGET_SURROUND: #pragma message("==========================피격자라는 발동대상이 필요하나?") case xIVT_ATTACKED_TARGET_RADIUS: case xIVT_ATTACKED_TARGET_SURROUND: { // 여기에 case를 추가시킨다면 아래 if에도 추가할것. XSkillUser *pCaster = this; // XSkillReceiver *pInvoker = pCastTarget; // if( pInvoker == nullptr || pInvoker->GetCamp() == 0/*xSIDE_NONE*/ ) // pInvoker = pCaster->GetThisRecv(); // XBREAK( pInvoker == nullptr ); BIT bitSideSearchFilt = GetFilterSideInvoke( pCaster, pCastTarget, pEffect->invokeTarget, filtIvkFriendship ); int numApply = pEffect->invokeNumApply; // 0이면 제한없음. if( typeIvkTarget == xIVT_CAST_TARGET_RADIUS || typeIvkTarget == xIVT_ATTACKED_TARGET_RADIUS ) { if( pCastTarget ) { aryTempInvokes.Add( pCastTarget ); if( numApply > 1 ) --numApply; // 시전대상은 포함시켰으므로 적용수가 있었다면 하나 빼준다. 적용수가 1이면 그냥 추가한마리로 처리함. } } // 발동자를 중심으로(발동자를 포함하거나/제외하거나) 반경내 sideSearchFilt에 해당하는 // side편 대로 검색하여 invokeNumApply개의 리스트를 요청한다 float size = pEffect->GetInvokeSize( level ); if( size == 0 ) { size = pEffect->castSize.w; } size = pCaster->OnInvokeTargetSize( pDat, pEffect, level, pCastTarget, size ); GetListObjsRadius( &aryTempInvokes, pDat, pEffect, pCastTarget, // 원의 중심이 되는 타겟 vCastTarget, // 원의 중심 좌표 size, bitSideSearchFilt, numApply, FALSE ); } break; case xIVT_CAST_TARGET_PARTY: // 시전대상파티 case xIVT_ATTACKED_TARGET_PARTY: // 피격자파티 if( XASSERT(pCastTarget) ) { // 기준타겟으로부터 그룹내 오브젝트들을 의뢰한다. pCastTarget->GetGroupList( &aryTempInvokes, pDat, pEffect ); } break; case xIVT_CURR_TARGET: { // 현재 공격대상을 얻는다.(시전대상과 관계없이 현재 타겟을 얻는다) auto pCurrTarget = GetCurrTarget(); // virtual if( pCurrTarget && IsInvokeAble( pDat, pCurrTarget, pEffect ) ) aryTempInvokes.push_back( pCurrTarget ); } break; // 현재타겟좌표 case xIVT_CURR_TARGET_POS: { auto pCurrTarget = GetCurrTarget(); // virtual if( pCurrTarget ) { *pOutIvkTarget = pCurrTarget->GetvPosFromSkill(); } } break; // 타격자 case xIVT_ATTACKER: { auto pAttacker = pCastTarget->GetpAttacker(); if( pAttacker && IsInvokeAble( pDat, pAttacker, pEffect ) ) aryTempInvokes.push_back( const_cast<XSkillReceiver*>( pAttacker ) ); } break; case xIVT_RANDOM_PARTY: { xtGroup typeGroup; if( filtIvkFriendship & xfALLY ) typeGroup = xGT_RANDOM_PARTY_FRIENDLY; else if( filtIvkFriendship & xfHOSTILE ) typeGroup = xGT_RANDOM_PARTY_ENEMY; auto pRecv = GetThisRecv(); pRecv->GetGroupList( &aryTempInvokes, pDat, pEffect, typeGroup ); } break; // 모두 case xIVT_ALL: { xtGroup typeGroup; if( filtIvkFriendship & xfALLY ) typeGroup = xGT_FRIENDLY_ALL; else if( filtIvkFriendship & xfHOSTILE ) typeGroup = xGT_ENEMY_ALL; auto pRecv = GetThisRecv(); pRecv->GetGroupList( &aryTempInvokes, pDat, pEffect, typeGroup ); } break; default: XBREAKF(1, "잘못된 발동파라메터:%d", typeIvkTarget ); break; } // switch // if( aryTempInvokes.size() > 0 ) { // 현재 사용되는곳이 없는듯. // CustomInvokeFilter( _plistOutInvokeTarget, aryTempInvoker, pEffect ); (*_plistOutInvokeTarget) = aryTempInvokes; } return _plistOutInvokeTarget->size(); }
// 클라이언트로부터 패킷을 받음. BOOL XClientConnection::ProcessPacket(DWORD idPacket, ID idKey, XPacket& p) { TRACE( "recv packet: %d - \n", idPacket ); int retv = 1; if ( idPacket == xCL2GS_ACCOUNT_REQ_LOGIN ) RecvLogin(p); else { auto pUser = SafeCast<XGameUser*>(GetspUser().get()); if (XBREAK(pUser == nullptr)) { CONSOLE("idPacket=%d, idConnect=0x%08x", idPacket, GetidConnect()); OnInvalidVerify(); // DoDisconnect(); return FALSE; } switch (idPacket) { // case xCL2GS_ACCOUNT_REQ_LOGIN: RecvLogin(p); break; //case xCL2GS_ACCOUNT_NICKNAME_DUPLICATE: retv = pUser->RecvAccountNickNameDuplicate(p); break; //case xCL2GS_ACCOUNT_NAME_DUPLICATE: retv = pUser->RecvAccountNameDuplicate(p); break; case xCL2GS_ACCOUNT_NAME_REGIST: retv = pUser->RecvAccountNameRegist(p); break; // case xCL2GS_ACCOUNT_LOGIN_FROM_ID: retv = pUser->RecvAccountNameLogin(p); break; case xCL2GS_ACCOUNT_NICKNAME_CHANGE: retv = pUser->RecvAccountNickNameChange(p); break; case xCL2GS_LOBBY_SPOT_RECON: retv = pUser->RecvSpotRecon(p); break; case xCL2GS_LOBBY_SPOT_ATTACK: retv = pUser->RecvSpotAttack(p); break; case xCL2GS_INGAME_REQ_FINISH_BATTLE: retv = pUser->RecvReqFinishBattle2(p); break; case xCL2GS_LOBBY_SPOT_COLLECT: retv = pUser->RecvSpotCollect(p); break; case xCL2GS_LOBBY_OPEN_CLOUD: retv = pUser->RecvOpenCloud(p); break; // case xCL2GS_LOBBY_ADD_HERO_EXP: retv = pUser->RecvAddHeroExp(p); break; //영웅 정보가 변경 되었습니다. case xCL2GS_LOBBY_CHANGE_HERO_LEGION: retv = pUser->RecvChageHeroLegion(p); break; case xCL2GS_LOBBY_CHANGE_HERO_EQUIPMENT:retv = pUser->RecvChageHeroEquip(p); break; case xCL2GS_LOBBY_SUMMON_HERO: retv = pUser->RecvSummonHero(p); break; case xCL2GS_LOBBY_NEW_SQUAD: retv = pUser->RecvNewSquad(p); break; case xCL2GS_LOBBY_MOVE_SQUAD: retv = pUser->RecvMoveSquad(p); break; case xCL2GS_LOBBY_CHANGE_SQUAD: retv = pUser->RecvChangeSquad(p); break; case xCL2GS_LOBBY_ITEM_SHOP_LIST_CASH: retv = pUser->RecvItemSellList(p); break; // case xCL2GS_LOBBY_ITEM_SHOP_LIST_TIME: retv = pUser->RecvItemSellList(p); break; ///< 시간 만료 아이템 상점 판매 목록 case xCL2GS_LOBBY_ITEM_BUY: retv = pUser->RecvBuyItem(p); break; ///< 아이템 구매 case xCL2GS_LOBBY_ITEM_SELL: retv = pUser->RecvSellItem(p); break; ///< 아이템 상점에 판매 case xCL2GS_LOBBY_ITEM_SPENT: retv = pUser->RecvItemSpent(p); break; ///< 아이템 사용 case xCL2GS_LOBBY_INVENTORY_EXPAND: retv = pUser->RecvInventoryExpand(p); break; ///< 인벤토리 확장 case xCL2GS_CAMP_REWARD: retv = pUser->RecvCampaignReward( p ); break; case xCL2GS_TRAIN_HERO_BY_GOLD: retv = pUser->RecvTrainHeroByGold( p ); break; case xCL2GS_INIT_ABIL: retv = pUser->RecvInitAbil( p ); break; // #ifdef _INAPP_GOOGLE case xCL2GS_LOBBY_CASH_ITEM_BUY_PAYLOAD:retv = pUser->RecvCashItemBuyPayload(p); break; ///< Inapp 구글플레이_payload case xCL2GS_LOBBY_CASH_ITEM_BUY_IAP: retv = pUser->RecvBuyCashtemIAP(p); break; ///< Inapp 구글플레이 //#endif // #ifdef _INAPP_APPLE // case xCL2GS_LOBBY_CASH_ITEM_BUY_IAP_IOS:retv = pUser->RecvCashItemBuyApple(p); break; ///< Inapp 구매_애플 // #endif case xCL2GS_CHEAT: retv = pUser->RecvCheat(p); break; case xCL2GS_CHEAT_CREATE_ITEM: retv = pUser->RecvCheatCreateItem(p); break; case xCL2GS_LOBBY_POST_INFO: pUser->RecvPostInfoRequest(p); break; //클라이언트 우편함 정보 요청 //case xCL2GS_LOBBY_POST_READ: pUser->RecvPostReadRequest(p); break; //클라이언트 우편함 읽음.(상대편에게 알려 줄까 말까?) case xCL2GS_LOBBY_POST_GETITEM_ALL: pUser->RecvPostItemGetRequestAll(p); break; //클라이언트 우편물 수령요청 //case xCL2GS_LOBBY_POST_DELETE: pUser->RecvPostDeleteRequest(p); break; //클라이언트 우편물 삭제 요청 case xCL2GS_LOBBY_TRADE: retv = pUser->RecvTrade(p); break; case xCL2GS_LOBBY_CHANGE_SCALP_TO_BOOK: retv = pUser->RecvChangeScalpToBook(p); break; // case xCL2GS_LOOBY_UPGRADE_SQUAD: retv = pUser->RecvUpgradeSquad(p); break; case xCL2GS_LOBBY_RELEASE_HERO: retv = pUser->RecvReleaseHero(p); break; // case xCL2GS_LOBBY_LEVELUP_SKILL: retv = pUser->RecvLevelUpSkill(p); break; case xCL2GS_LOBBY_RANKING_INFO: retv = pUser->RecvRankingInfo(p); break; // pUser->SendSubscribePackage(); break;//pUser->Cheat_AddPostInfo(); break; case xCL2GS_LOBBY_CASH_TRADE_CALL: retv = pUser->RecvTradeCashCall(p); break; // 캐쉬로 무역상 호출. // case xCL2GS_LOBBY_TIME_TRADE_CALL: retv = pUser->RecvTradeTimeCall(p); break; // 시간으로 무역상 호출. case xCL2GS_PROMOTION_HERO: retv = pUser->RecvPromotionHero( p ); break; case xCL2GS_SUMMON_HERO_BY_PIECE: retv = pUser->RecvSummonHeroByPiece( p ); break; case xCL2GS_UI_ACTION: retv = pUser->RecvUIAction( p ); break; case xCL2GS_LOBBY_GUILD_INFO: retv = pUser->RecvGuildInfo(p); break; // case xCL2GS_LOBBY_GUILD_ALL_INFO: retv = pUser->RecvAllGuildInfo(p); break; case xCL2GS_LOBBY_GUILD_CREATE: retv = pUser->RecvGuildCreate(p); break; case xCL2GS_LOBBY_GUILD_CHANEGE_OPTION: retv = pUser->RecvGuildChangeOption(p); break; case xCL2GS_LOBBY_GUILD_CHANEGE_CONTEXT:retv = pUser->RecvGuildChangeContext(p);break; case xCL2GS_LOBBY_GUILD_CHANGE_MEMBER: retv = pUser->RecvGuildChangeMemberInfo(p); break; case xCL2GS_LOBBY_GUILD_JOIN_REQ: retv = pUser->RecvGuildJoinReq(p); break; case xCL2GS_LOBBY_GUILD_JOIN_ACCEPT: retv = pUser->RecvGuildJoinAccept(p); break; case xCL2GS_LOBBY_GUILD_OUT: retv = pUser->RecvGuildOut(p); break; case xCL2GS_LOBBY_GUILD_KICK: retv = pUser->RecvGuildKick(p); break; case xCL2GS_LOBBY_GUILD_BUY_ITEM: retv = pUser->RecvBuyGuildItem( p ); break; case xCL2GS_QUEST_REQUEST_REWARD: retv = pUser->RecvReqQuestReward(p); break; case xCL2GS_LOBBY_SPOT_TOUCH: retv = pUser->RecvSpotTouch(p); break; case xCL2GS_CAMP_CLICK_STAGE: retv = pUser->RecvClickStageInCampaign(p); break; case xCL2GS_TECH_RESEARCH: retv = pUser->RecvResearch(p); break; case xCL2GS_TECH_LOCK_FREE: retv = pUser->RecvAbilLockFree(p); break; case xCL2GS_TECH_RESEARCH_COMPLETE_NOW: retv = pUser->RecvResearchCompleteNow(p); break; case xCL2GS_RESEARCH_COMPLETE: retv = pUser->RecvCheckResearchComplete(p); break; case xCL2GS_LOBBY_REGEN_SPOT: retv = pUser->RecvRegenSpot(p); break; case xCL2GS_LOBBY_REMATCH_SPOT: retv = pUser->RecvReMatchSpot(p); break; case xCL2GS_INGAME_SULFUR_RETREAT: retv = pUser->RecvSulfurRetreat(p); break; case xCL2GS_INGAME_BATTLE_START: retv = pUser->RecvBattleStart(p); break; case xCL2GS_LOBBY_WITHDRAW_MANDRAKE: retv = pUser->RecvWithdrawMandrake(p); break; // case xCL2GS_TRAIN_HERO: retv = pUser->RecvTrainHero(p); break; case xCL2GS_CHECK_TRAIN_COMPLETE: retv = pUser->RecvCheckTrainComplete(p); break; case xCL2GS_CHANGE_HELLO_MSG: retv = pUser->RecvChangeHelloMsg( p ); break; case xCL2GS_UNLOCK_TRAINING_SLOT: retv = pUser->RecvUnlockTrainingSlot( p ); break; // case xCL2GS_TRAIN_COMPLETE_TOUCH: retv = pUser->RecvLevelupConfirm(p); break; case xCL2GS_AP_CHECK_TIMEOVER: retv = pUser->RecvCheckAPTimeOver( p ); break; case xCL2GS_ACCEPT_LEVELUP: retv = pUser->RecvAccepLevelUp( p ); break; case xCL2GS_BIT_FLAG_TUTORIAL: retv = pUser->RecvFlagTutorial( p ); break; case xCL2GS_TECH_UNLOCK_UNIT: retv = pUser->RecvUnlockUnit( p ); break; case xCL2GS_FILL_AP: retv = pUser->RecvSendReqFillAP( p ); break; case xCL2GS_TRAIN_COMPLETE_QUICK: retv = pUser->RecvTrainCompleteQuick( p ); break; case xCL2GS_CLICK_FOG_SQUAD: retv = pUser->RecvClickFogSquad( p ); break; case xCL2GS_CHECK_UNLOCK_UNIT: retv = pUser->RecvCheckUnlockUnit( p ); break; case xCL2GS_TOUCH_SQUAD_IN_READY: retv = pUser->RecvTouchSquadInReadyScene( p ); break; case xCL2GS_CONTROL_SQUAD_IN_BATTLE: retv = pUser->RecvControlSquadInBattle( p ); break; case xCL2GS_CHECK_ENCOUNTER_LOG: retv = pUser->RecvCheckEncounterLog( p ); break; case xCL2GS_GOTO_HOME: retv = pUser->RecvGotoHome( p ); break; case xCL2GS_ACCOUNT_REGISTER_FACEBOOK: retv = pUser->RecvRegisterFacebook( p ); break; // case xCL2GS_OPEN_GUILD_RAID: retv = pUser->RecvSendReqGuildRaidOpen( p ); break; case xCL2GS_END_SEQ: retv = pUser->RecvEndSeq( p ); break; case xCL2GS_REGIST_PUSHMSG: pUser->RecvPushMsgRegist(p); break; case xCL2GS_UNREGIST_PUSHMSG: pUser->RecvPushMsgUnRegist(p); break; case xCL2GS_PUSH_GCM_REGIST_ID: retv = pUser->RecvGCMResistId( p ); break; case xCL2GS_LOBBY: pUser->Cheat_AddPostInfo(); break; //임시 패킷.( 서버 테스트용으로만 사용합니다. 사용을 자재해주세요.) case xCL2GS_PAYMENT_ASSET: retv = pUser->RecvPaymentAssetByGem( p ); break; case xCL2GS_PRIVATE_RAID_ENTER_LIST: retv = pUser->RecvPrivateRaidEnterList( p ); break; case xCL2GS_SPOT_UPDATE_FOR_BATTLE: retv = pUser->RecvUpdateSpotForBattle( p ); break; case xCL2GS_ENTER_READY_SCENE: retv = pUser->RecvEnterReadyScene( p ); break; case xCL2GS_SYNC: retv = pUser->RecvSync( p ); break; case xCL2GS_SHOW_ADS: retv = pUser->RecvShowAdsVideo( p ); break; case xCL2GS_FINISH_SHOW_ADS: retv = pUser->RecvDidFinishShowAdsVideo( p ); break; case xCL2GS_POST_DELETE: retv = pUser->RecvPostDelete( p ); break; case xCL2GS_MEDAL_CLICK_STAGE: retv = pUser->RecvClickStageInMedal( p ); break; case xCL2GS_HERO_CLICK_STAGE: retv = pUser->RecvClickStageInHero( p ); break; case xCL2GS_GUILD_RAID_CLICK_STAGE: retv = pUser->RecvClickStageInGuildRaid( p ); break; case xCL2GS_REQ_EQUIP: retv = pUser->RecvSyncEquip( p ); break; default: // 알수없는 패킷이 날아왔다. XBREAKF(1, "unknown packet 0x%8x", idPacket); { DoDisconnect(); return FALSE; } break; } } TRACE( "recv packet: end\n" ); // 불량 패킷 보내서 0을 리턴한 유저는 즉각 끊어버린다. if( retv == 0 ) OnInvalidVerify(); return TRUE; }
void XSurfaceOpenGL::Blt( const DWORD *pSrc, RECT *pmemSrcRect, // 소스의 일부분만 옮기고 싶을때. 널이면 전체 int bytePerPixel, // pSrc의 bytePerPixel xAlpha alpha, float _memSrcw, float _memSrch, XCOLOR dwKeyColor, BOOL bSrcKeep ) { GLint memSrcw = (GLint)_memSrcw; GLint memSrch = (GLint)_memSrch; glGenTextures(1, &m_textureID); if( XBREAKF( m_textureID == 0, "w:%d h:%d", memSrcw, memSrch ) ) return; const GLsizei alignedW = m_nAlignedWidth; // 이미 CreateBlank를 했다는 가정. const GLsizei alignedH = m_nAlignedHeight; if( pSrc ) // NULL이면 빈텍스쳐로 만듬. { void *alignedImg = NULL; if( bytePerPixel == 2 ) { XBREAK(1); // pSrcRect지원땜에 많이 바꼈으니 다시 작성할것 /* if( alpha == xALPHA ) { m_format = GL_RGBA; m_type = GL_UNSIGNED_BYTE; // 2^단위로 정렬된 크기로 텍스쳐를 만들기위해 임시버퍼에 한번찍고 그것을 다시 텍스쳐로 전송한다. { DWORD *temp, *_temp, rgba; temp = _temp = (DWORD *)malloc( alignedW * alignedH * sizeof(DWORD) ); memset( temp, 0, alignedW * alignedH * sizeof(DWORD) ); const WORD *src = (const WORD *)pSrc; BYTE r = XCOLOR_RGB_R( dwKeyColor ); BYTE g = XCOLOR_RGB_G( dwKeyColor ); BYTE b = XCOLOR_RGB_B( dwKeyColor ); WORD wKeyColor = XCOLOR_RGB565( r, g, b ); int i, j; WORD data; for( i = 0; i < memSrch; i ++ ) { for( j = 0; j < memSrcw; j ++ ) { data = *src++; if( data == wKeyColor ) rgba = GRAPHICS->Convert565ToRGBA8( data, 0 ); else rgba = GRAPHICS->Convert565ToRGBA8( data, 255 ); *_temp++ = rgba; } _temp += (alignedW - memSrcw); } alignedImg = temp; } } else { m_format = GL_RGB; m_type = GL_UNSIGNED_SHORT_5_6_5; SetSrcImg( (WORD*)pSrc, memSrcw, memSrch ) // bSrcKeep이 TRUE면 원본크기와 정렬된 크기가 같은지 여부에 관계없이 복사본을 만들어야 한다. if( bSrcKeep || (memSrcw != alignedW || memSrch != alignedH) ) // 정렬된 크기가 같으면 굳이 재배열할필요 없다. { // 2^단위로 정렬된 크기로 텍스쳐를 만들기위해 임시버퍼에 한번찍고 그것을 다시 텍스쳐로 전송한다. WORD *temp, *_temp; int size = alignedW * alignedH * sizeof(WORD); temp = _temp = (WORD *)malloc( size ); memset( temp, 0, size ); const WORD *src = (const WORD *)pSrc; int i, j; for( i = 0; i < memSrch; i ++ ) { for( j = 0; j < memSrcw; j ++ ) *_temp++ = *src++; _temp += (alignedW - memSrcw); } alignedImg = temp; } } */ } else if( bytePerPixel == 4 ) { m_format = GL_RGBA; m_type = GL_UNSIGNED_BYTE; if( pmemSrcRect == NULL ) // 이미지전체 { int dstw = memSrcw, dsth = memSrch; int dstSize = dstw * dsth; if( bSrcKeep ) // 이미지 보관 { DWORD *pImg = new DWORD[ dstSize ]; memcpy( pImg, pSrc, dstSize * sizeof(DWORD) ); SetSrcImg( (DWORD *)pImg, dstw, dsth ); } else SetSrcImg( NULL, dstw, dsth ); // 2^단위로 정렬된 크기로 텍스쳐를 만들기위해 임시버퍼에 한번찍고 그것을 다시 텍스쳐로 전송한다. { DWORD *_temp; alignedImg = _temp = new DWORD[ alignedW * alignedH ]; memset( alignedImg, 0, alignedW * alignedH * sizeof(DWORD) ); const DWORD *src = (const DWORD *)pSrc; int i, j; for( i = 0; i < memSrch; i ++ ) { for( j = 0; j < memSrcw; j ++ ) { *_temp++ = *src++; } _temp += (alignedW - memSrcw); } } } else { // 이미지 일부분만 옮김 int memDstw = (pmemSrcRect->right - pmemSrcRect->left + 1); int memDsth = (pmemSrcRect->bottom - pmemSrcRect->top + 1); int dstSize = memDstw * memDsth; if( bSrcKeep ) { DWORD *pDst = new DWORD[ dstSize ]; DWORD *_pDst = pDst; const DWORD *_pSrc = pSrc + (pmemSrcRect->top * memSrcw + pmemSrcRect->left); for( int i = 0; i < memDsth; i ++ ) { for( int j = 0; j < memDstw; j ++ ) { *_pDst++ = *_pSrc++; } _pSrc += (memSrcw - memDstw); } SetSrcImg( (DWORD *)pDst, memDstw, memDsth ); } else SetSrcImg( NULL, memDstw, memDsth ); // 정렬된 이미지 만들기 { DWORD *_temp = new DWORD[ alignedW * alignedH ]; alignedImg = (void *)_temp; memset( alignedImg, 0, alignedW * alignedH * sizeof(DWORD) ); const DWORD *_pSrc = pSrc + (pmemSrcRect->top * memSrcw + pmemSrcRect->left); int i, j; for( i = 0; i < memDsth; i ++ ) { for( j = 0; j < memDstw; j ++ ) { *_temp++ = *_pSrc++; } _temp += (alignedW - memDstw); _pSrc += (memSrcw - memDstw); } } } } glBindTexture(GL_TEXTURE_2D, m_textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, m_format, alignedW, alignedH, 0, m_format, m_type, alignedImg); DWORD *pTemp = (DWORD*)alignedImg; SAFE_DELETE_ARRAY( pTemp ); alignedImg = NULL; } else // (alignedImg) { if( alpha == xALPHA ) { m_format = GL_RGBA; m_type = GL_UNSIGNED_BYTE; } else { m_format = GL_RGB; m_type = GL_UNSIGNED_SHORT_5_6_5; } glBindTexture(GL_TEXTURE_2D, m_textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, m_format, alignedW, alignedH, 0, m_format, m_type, NULL ); } }
/** @brief pBaseTarget(혹은 vBaseTarget)을 기준으로 얻어지는 모든 시전대상을 얻는다. */ int XSkillUser::GetCastingTargetList( XVector<XSkillReceiver*> *pOutAry, // 시전대상얻기 결과가 담겨짐 XE::VEC2* pOutCastTarget, // 시전대상이 좌표형태가 될때. xtCastTarget castTarget, // 시전대상타입 const XSkillDat *pDat, // 스킬사용 오브젝트 const EFFECT *pEff, // 효과 int level, XSkillReceiver *pBaseTarget, const XE::VEC2& vBaseTarget ) { // 좌표에 값이 있으면 타겟은 널이어야 한다., XBREAK( vBaseTarget.IsNotZero() && pBaseTarget != nullptr ); // 둘다 값이 없을순 없다. XBREAK( vBaseTarget.IsZero() && pBaseTarget == nullptr ); // switch( castTarget ) { case xCST_BASE_TARGET: // 기준타겟 if( pBaseTarget ) { // 시전대상이 기준타겟인데 기준타겟이 없는경우는 없어야 한다. 이런경우의 시전대상은 리시버객체이므로 이전에 이미 처리되어 들어온다. pOutAry->Add( pBaseTarget ); } else if( vBaseTarget.IsNotZero() ) { // 좌표가 있고 시전대상이 기준타겟(좌표)이고 지속효과라면 바닥에 뿌리는 스킬이므로 리시버 객체를 만들어 그것을 시전대상으로 해야함. const float sec = pEff->GetDuration( level ); XBREAK( sec <= 0 ); auto pSfx = CreateSfxReceiver( vBaseTarget, pEff, sec ); pOutAry->Add( pSfx ); } break; case xCST_BASE_TARGET_RADIUS: // 기준타겟반경 case xCST_BASE_TARGET_SURROUND: { // 기준타겟주변 // 기준타겟을 중심으로 원형 반경내에서의 객체를 선택한다. BIT bitSearchFilter = GetFilterSideCast( GetThisRecv(), castTarget, pBaseTarget, pEff->castfiltFriendship ); int numApply = pEff->invokeNumApply; // 0이면 제한없음. // 기준타겟포함이면 기준타겟은 우선으로 리스트에 들어가고 기준타겟제외로 검색한다. if( castTarget == xCST_BASE_TARGET_RADIUS ) { if( pBaseTarget ) { pOutAry->Add( pBaseTarget ); if( numApply > 1 ) --numApply; } } float castSize = pEff->castSize.w; float sizeAdd = 0.f; float sizeAddMultiply = 0.f; // 시전범위 증폭 OnSkillAmplifyUser( pDat, nullptr, pEff, xEA_CAST_RADIUS, &sizeAddMultiply, &sizeAdd ); castSize += sizeAdd; castSize = castSize + castSize * sizeAddMultiply; numApply += (int)(pEff->invokeNumApply * sizeAddMultiply); // 기준타겟(혹은 기준좌표)를 기준으로 대상을 얻는다. GetListObjsRadius( pOutAry, pDat, pEff, pBaseTarget, // 기준타겟 vBaseTarget, // 기준타겟이 좌표형태일경우 castSize, bitSearchFilter, numApply, FALSE ); } break; case xCST_BASE_TARGET_PARTY: // 기준타겟파티 if( XASSERT(pBaseTarget) ) { // 기준타겟파티를 하면 기준타겟은 반드시 있어야 한다. // 기준타겟으로부터 그룹내 오브젝트들을 의뢰한다. pBaseTarget->GetGroupList( pOutAry, pDat, pEff ); } break; case xCST_BASE_TARGET_POS: { // 기준타겟좌표 auto vPos = vBaseTarget; if( pBaseTarget ) { // 기준타겟이 있었다면 기준타겟의 좌표/없으면 파라메터로 온 좌표에 vPos = pBaseTarget->GetvPosFromSkill(); } if( XASSERT(vPos.IsNotZero()) ) { // 좌표가 있고 시전대상이 기준타겟(좌표)이고 지속효과라면 바닥에 뿌리는 스킬이므로 리시버 객체를 만들어 그것을 시전대상으로 해야함. const float sec = pEff->GetDuration( level ); if( sec > 0 ) { // 시전대상(좌표)에 지속시간형이면 리시버 객체가 필요함. auto pSfx = CreateSfxReceiver( vPos, pEff, sec ); pOutAry->Add( pSfx ); } else { *pOutCastTarget = vPos; // 지속형이 아니면 시전대상은 좌표형이 된다.(파이어볼 폭발같은..) } } } break; default: XBREAKF( 1, "%d: 처리안된 castTarget", castTarget ); } return pOutAry->size(); }