#include "stdafx.h" #include "ArcadiaClient.h" #include #include #include "TerrainMapEngine.h" bool ArcadiaClient::FinishedReqRegionUpdate() { bool bIsFinished = m_myPos.Step( m_lastProcTime ); if( m_myPos.IsMoving() ) return false; m_intf->ReqRegionUpdate( m_lastProcTime - m_lastPendingTime[0] ); return true; } void ArcadiaClient::proc( ArMoveVector & pos ) { unsigned prev_x = GetRegionX( pos.GetX() ); unsigned prev_y = GetRegionY( pos.GetY() ); bool bIsFinished = m_myPos.Step( m_lastProcTime ); unsigned rx = GetRegionX( pos.GetX() ); unsigned ry = GetRegionY( pos.GetY() ); if( bIsFinished || prev_x != rx || prev_y != ry ) { // { 살짝 스쳐가는 region 은 무시하자 ArMoveVector mv; mv = pos; mv.Step( m_lastProcTime + IGNOREABLE_VISIT_TIME ); if( bIsFinished || ( mv.GetRX() == rx && mv.GetRY() == ry && mv.IsMoving() ) ) { m_intf->ReqRegionUpdate( m_lastProcTime - m_lastPendingTime[0] ); m_lastPendingTime[0] = m_lastProcTime; if( prev_x != rx || prev_y != ry ) { m_px = m_pnx; m_py = m_pny; m_pnx = rx; m_pny = ry; } } // } } } void ArcadiaClient::Proc( bool bPendingLeave ) { m_lastProcTime = GetArTime(); /* unsigned fprx = GetRegionX( GetMyPos().GetX() ); unsigned fpry = GetRegionY( GetMyPos().GetY() ); unsigned rx = GetRegionX( GetMyPos().GetX() ); unsigned ry = GetRegionY( GetMyPos().GetY() ); */ // update client pos if( m_myPos.IsMoving() ) proc( m_myPos ); _Object* client = NULL; bool res; if( bPendingLeave ) { _Object* client = NULL; res = m_clientList.get_first_value(client); while ( res ) { if (client->mv.IsMoving()) client->mv.Step(m_lastProcTime); res = m_clientList.get_next_value(client); } } else { res = m_clientList.get_first_value(client); while ( res ) { procClient(client); res = m_clientList.get_next_value(client); } } vector eraseList; res = m_clientList.get_first_value(client); while ( res ) { if (client->bIsLeaved && client->bIsActivate ) { if( client->bIsActivate = m_intf->onLeave( client ) ) { eraseList.push_back(client->handle); } } res = m_clientList.get_next_value(client); } size_t eraseCount = eraseList.size(); for (size_t i = 0; i < eraseCount; ++i) { m_clientList.erase(eraseList[i]); } eraseList.clear(); } void ArcadiaClient::ReqMove( AR_HANDLE handle, const ArPosition & target, const ArPosition * targetposdata, int count, bool bSpeedSync ) { if( m_myHandle == handle ) { ReqMove( target, targetposdata, count, bSpeedSync ); return; } AR_TIME gap = m_lastProcTime - m_lastPendingTime[handle]; m_intf->ReqMove( handle, GetPosition( handle ), target, m_lastProcTime, targetposdata, count, bSpeedSync ); // 15 는 메세지 전송 왔다갔다 하는 시간 갭.. m_lastPendingTime[handle] = m_lastProcTime; } void ArcadiaClient::ReqMove( const ArPosition & target, const ArPosition * targetposdata, int count, bool bSpeedSync ) { //if( bIsPendingMove ) return; bIsPendingMove = true; AR_TIME gap = m_lastProcTime - m_lastPendingTime[0]; m_targetPos = target; m_intf->ReqMove( m_myHandle, GetMyPos(), m_targetPos, m_lastProcTime, targetposdata, count ); // 15 는 메세지 전송 왔다갔다 하는 시간 갭.. m_lastPendingTime[0] = m_lastProcTime; } void ArcadiaClient::onLogin( const ArPosition & pPos, AR_HANDLE my_handle ) { m_myHandle = my_handle; m_myPos.SetCurrentPos( pPos ); m_pnx = m_px = GetRegionX( pPos.x ); m_pny = m_py = GetRegionY( pPos.y ); } void ArcadiaClient::ReSet() { m_myHandle = 0; m_myPos.StopMove(); m_myPos = ArMoveVector(); } void ArcadiaClient::StopMove() { // 이동정지 m_myPos.StopMove(); } void ArcadiaClient::ClerAll() { m_clientList.clear(); } void ArcadiaClient::onMoveAck( AR_TIME start_time,unsigned char speed ) { } void ArcadiaClient::onEnter( _Object * pPtr ) { if (m_clientList.lookup(pPtr->handle)) return ; m_clientList.add(pPtr->handle, pPtr); } //활성화 or 비활성화 void ArcadiaClient::SetActivate( AR_HANDLE handle ) { _Object* client; if (m_clientList.lookup(handle, client)) { client->bIsActivate = true; client->bIsLeaved = false; } } _Object * ArcadiaClient::onLeave( AR_HANDLE handle ) { _Object* client; if (m_clientList.lookup(handle, client)) { m_clientList.erase(handle); return client; } return NULL; } void ArcadiaClient::onMove( AR_HANDLE id, const ArPosition & pos, unsigned char speed, AR_TIME start_time ) { if( id == m_myHandle ) { m_myPos.SetMove( pos, speed, m_lastProcTime, GetArTime() ); bIsPendingMove = false; return; } _Object* client; if (m_clientList.lookup(id, client)) { client->mv.SetMove( pos, speed, start_time, GetArTime() ); } } void ArcadiaClient::onMultiMove( AR_HANDLE id, const ArPosition & pos, const std::vector< ArPosition > & _to, unsigned char speed, AR_TIME start_time ) { if( id == m_myHandle ) { m_myPos.SetMultipleMove( _to, speed, m_lastProcTime, GetArTime() ); bIsPendingMove = false; return; } _Object* client; if (m_clientList.lookup(id, client)) { client->mv.SetMultipleMove( _to, speed, m_lastProcTime, GetArTime() ); } } void ArcadiaClient::onKnockBack( AR_HANDLE id, const ArPosition & pos, unsigned char speed ) { if( id == m_myHandle ) { m_myPos.SetKnockBack( pos, speed, m_lastProcTime, GetArTime() ); bIsPendingMove = false; return; } _Object* client; if (m_clientList.lookup(id, client)) { client->mv.SetKnockBack( pos, speed, m_lastProcTime, GetArTime() ); } } void ArcadiaClient::onRegionAck( unsigned rx, unsigned ry ) { _Object* client = NULL; bool res = m_clientList.get_first_value(client); while ( res ) { if( client->mv.IsMoving() ) { client->mv.Step( m_lastProcTime ); } // { leave 해야할 녀석을 세팅 & 인터페이스로 알려주자 int crx = client->mv.GetRX(); int cry = client->mv.GetRY(); if( !IsVisibleRegion( crx, cry, rx, ry ) && !IsVisibleRegion( crx, cry, m_myPos.GetRX(), m_myPos.GetRY() ) ) { if( !client->leaveTime ) client->leaveTime = m_lastProcTime; else { if( client->leaveTime + 50 < m_lastProcTime ) { client->bIsLeaved = true; } } } res = m_clientList.get_next_value(client); } vector eraseList; res = m_clientList.get_first_value(client); while ( res ) { //활성화 돼있나? true( 화면에 보여지고 있다 ) Creature에만 해당 if( client->bIsLeaved && client->bIsActivate ) { if( client->bIsActivate = m_intf->onLeave( client ) ) { eraseList.push_back(client->handle); } } res = m_clientList.get_next_value(client); } size_t eraseCount = eraseList.size(); for (size_t i = 0; i < eraseCount; ++i) { m_clientList.erase(eraseList[i]); } eraseList.clear(); } void ArcadiaClient::onWarp( AR_UNIT x, AR_UNIT y, AR_UNIT z ) { // 이동정지 m_myPos.Step( 0xffffffff ); // 다 날리고 vector eraseList; _Object* client = NULL; bool res = m_clientList.get_first_value(client); while ( res ) { client->mv.StopMove(); if( m_intf->onLeave( client ) ) { eraseList.push_back(client->handle); } res = m_clientList.get_next_value(client); } size_t eraseCount = eraseList.size(); for (size_t i = 0; i < eraseCount; ++i) { m_clientList.erase(eraseList[i]); } eraseList.clear(); m_myPos.StopMove(); m_myPos.SetCurrentXY( x, y ); m_myPos.SetCurrentZ( z ); } void ArcadiaClient::setTerrainMapEngine(CTerrainMapEngine* terrainMapEngine) { m_terrainMapEngine = terrainMapEngine; } void ArcadiaClient::calcNextKMovePos(sNextKMoveInfo& info, float oneStepMoveLen, float rateLen) { float len = oneStepMoveLen * rateLen; ArPosition offset; offset.x = ::cosf(info.kmoveDir) * len; offset.y = ::sinf(info.kmoveDir) * len; offset.z = 0.0f; info.nextKMovePos.x = info.curPos.x + offset.x; info.nextKMovePos.y = info.curPos.y + offset.y; info.nextKMovePos.z = info.curPos.z + offset.z; } bool ArcadiaClient::getNextKMovePos(sNextKMoveInfo& info, float oneStepMoveLen, std::vector const& blockList, float rateLen) { calcNextKMovePos(info, rateLen, oneStepMoveLen); bool collision; if (!blockList.empty()) { collision = m_terrainMapEngine->collisionCustomBlock(info.curPos.x, info.curPos.y, info.nextKMovePos.x, info.nextKMovePos.y, blockList); if (collision) { info.elapsedArTime = calcElapsedMoveTime(oneStepMoveLen, info.speed); AR_UNIT len = info.curPos.GetDistance(info.nextKMovePos); if (2 >= len) return true; /// 타겟 까지 이동은 해야 되기 때문에 false를 리턴한다. return false; } } collision = m_terrainMapEngine->collisionAttrQuad(info.curPos.x, info.curPos.y, info.nextKMovePos.x, info.nextKMovePos.y, info.collisionTheta); if (collision) { ++info.collisionCount; if (info.checkNextCollisionPos) { info.kmoveDir = info.collisionTheta; info.checkNextCollisionPos = false; return getNextKMovePos(info, oneStepMoveLen, blockList, rateLen); } } else { info.elapsedArTime = calcElapsedMoveTime(oneStepMoveLen, info.speed); } return collision; } AR_TIME ArcadiaClient::calcElapsedMoveTime(float len, int speed) const { return len / ((float)speed/SPEED_UNIT);; } void ArcadiaClient::onClientMultiMove( AR_HANDLE id, const ArPosition & pos, const std::vector< ArPosition > & _to, unsigned char speed, AR_TIME start_time ) { _Object* client = NULL; if (m_clientList.lookup(id, client)) { client->mv.SetMultipleMove( _to, speed, m_lastProcTime, GetArTime() ); #ifdef KMOVE_DEBUG addKMovePrimitive(_to, client->mv.GetPos(), 0); #endif } } #ifdef KMOVE_DEBUG void ArcadiaClient::addKMovePrimitive(std::vector const& _to, ArPosition const& curPos, int type) { if (_to.empty()) return ; if (m_kmovePrimitive->GetWireVertexCnt() > 100) m_kmovePrimitive->Clear(); K3DVector v1, v2; std::vector::const_iterator it = _to.end() - 1; ArPosition toPos = (*it); KColor color(0, 255, 0, 255); float offset = 3.0f; if (0 != type) { offset = 5.0f; color = KColor(0, 255, 255, 255); } /// 현재 위치 v1.Set(curPos.x, curPos.y, curPos.z + offset); v2.Set(toPos.x, toPos.y, toPos.z+offset+2.0f); m_kmovePrimitive->AddLine(v1, v2, color); } KWireUtilPrimitive* ArcadiaClient::getKMovePrimitive() const { return m_kmovePrimitive; } #endif void ArcadiaClient::procClient(_Object* client) { if( client->mv.IsMoving() ) { client->mv.Step( m_lastProcTime); } // { leave 해야할 녀석을 세팅 & 인터페이스로 알려주자 int crx = client->mv.GetRX(); int cry = client->mv.GetRY(); if( !IsVisibleRegion( crx, cry, m_myPos.GetRX(), m_myPos.GetRY() ) ) { if( !client->leaveTime ) { client->leaveTime = m_lastProcTime; } else { if( m_myPos.IsMoving() ) { ArMoveVector afterPos = m_myPos; afterPos.Step( 100 ); if( m_myPos.GetDistance( client->mv.GetPos() ) < afterPos.GetDistance( client->mv.GetPos() ) ) { client->bIsLeaved = true; } } else { if( client->leaveTime + 100 < m_lastProcTime ) { client->bIsLeaved = true; } } } } } void ArcadiaClient::setSpeed(AR_HANDLE id, unsigned char speed) { if (m_myHandle == id) { m_myPos.setSpeed(speed); } }