502 lines
11 KiB
C++
502 lines
11 KiB
C++
#include "stdafx.h"
|
|
#include "ArcadiaClient.h"
|
|
#include <mmo/ArOption.h>
|
|
#include <toolkit/XConsole.h>
|
|
#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<AR_HANDLE> 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<AR_HANDLE> 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<AR_HANDLE> 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<K3DVector2> 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<ArPosition> const& _to, ArPosition const& curPos, int type)
|
|
{
|
|
if (_to.empty())
|
|
return ;
|
|
|
|
if (m_kmovePrimitive->GetWireVertexCnt() > 100)
|
|
m_kmovePrimitive->Clear();
|
|
|
|
K3DVector v1, v2;
|
|
std::vector<ArPosition>::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);
|
|
}
|
|
}
|