Restructure repository to include all source folders

Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,775 @@
#include "CharSphereTree.h"
#include <cassert>
#include <Creature/Character/Character.h>
#include <Network/Dispatch/GameClient/GameClientDispatch.h>
CCharSphereTree& CCharSphereTree::GetInstance()
{
static CCharSphereTree ms_this( SphereConst::MAX_SPHERE_NODE,
SphereConst::DEFAULT_ROOT_SIZE,
SphereConst::DEFAULT_LEAF_SIZE,
SphereConst::DEFAULT_GRAVY );
return ms_this;
}
CCharSphereNode::CCharSphereNode() :
m_dwCID(0),
m_pCharacter(NULL),
m_pParent(NULL),
m_pChildren(NULL),
m_pPrevSibling(NULL),
m_pNextSibling(NULL),
m_ppRecomuteFifo(NULL),
m_ppIntegrateFifo(NULL),
m_iChildCount(0),
m_dwFlag(0),
m_fBindingDistance2(0),
m_pLink(NULL),
m_pTree(NULL)
{
}
CCharSphereNode::CCharSphereNode( CCharSphereTree* pTree, const Position& Pos, float fRadius, void* pLink ) :
CSphere(Pos, fRadius),
m_dwCID(0),
m_pCharacter(NULL),
m_pParent(NULL),
m_pChildren(NULL),
m_pPrevSibling(NULL),
m_pNextSibling(NULL),
m_ppRecomuteFifo(NULL),
m_ppIntegrateFifo(NULL),
m_iChildCount(0),
m_dwFlag(0),
m_fBindingDistance2(0),
m_pLink(pLink),
m_pTree(pTree)
{
}
void
CCharSphereNode::Init( CCharSphereTree* pTree, const Position& Pos, float fRadius, void* pLink )
{
m_pTree = pTree;
m_Center = Pos;
SetRadius( fRadius );
m_pLink = pLink;
}
void
CCharSphereNode::AddChild( CCharSphereNode* pChild )
{
CCharSphereNode* pOldChild = m_pChildren;
m_pChildren = pChild;
pChild->SetNextSibling( pOldChild );
pChild->SetPrevSibling( NULL );
pChild->SetParent( this );
if ( pOldChild )
{
pOldChild->SetPrevSibling( pChild );
}
++m_iChildCount;
float fDist = Distance2( pChild );
float fRadius = sqrtf( fDist ) + pChild->GetRadius();
assert( fRadius <= GetRadius() );
}
void
CCharSphereNode::DeleteChild( CCharSphereNode* pChild )
{
assert( m_iChildCount );
assert( m_pChildren );
#ifdef _DEBUG
// pChild 가 현재 노드의 자식인지 체크
CCharSphereNode* pChildren = m_pChildren;
bool bFound = false;
while ( pChildren )
{
if ( pChildren == pChild )
{
assert( !bFound );
bFound = true;
break;
}
pChildren = pChildren->GetNextSibling();
}
assert( bFound );
#endif
// Prev 와 Next Sibling 다시 설정
CCharSphereNode* pPrev = pChild->GetPrevSibling();
if ( pPrev )
{
CCharSphereNode* pNext = pChild->GetNextSibling();
pPrev->SetNextSibling( pNext );
if ( pNext ) pNext->SetPrevSibling( pPrev );
}
else
{
CCharSphereNode* pNext = pChild->GetNextSibling();
m_pChildren = pNext;
if ( m_pChildren ) m_pChildren->SetPrevSibling( NULL );
}
--m_iChildCount;
if ( 0 == m_iChildCount && HasSphereNodeFlag( SNF_SUPERSPHERE ) )
{
m_pTree->DeleteSphere( this );
}
}
void
CCharSphereNode::Unlink()
{
// Recompute & Integrate Fifo 에서 제거한다.
if ( m_ppRecomuteFifo )
{
*m_ppRecomuteFifo = NULL;
m_ppRecomuteFifo = NULL;
}
if ( m_ppIntegrateFifo )
{
*m_ppIntegrateFifo = NULL;
m_ppIntegrateFifo = NULL;
}
if ( m_pParent )
{
m_pParent->DeleteChild( this );
}
assert( !m_pChildren );
m_pParent = NULL;
}
void
CCharSphereNode::NewPos( const Position& Pos )
{
// 새로운 좌표 설정
m_Center = Pos;
// 부모가 있고, 재구성되어야 할 플래그가 없다면, 재구성을 할지를 판단한다.
if ( m_pParent && !HasSphereNodeFlag( SNF_INTEGRATE ) )
{
// 부모와의 거리의 제곱값을 계산한다.
float fDistance2 = Distance2( m_pParent );
// 거리가 바인딩 거리를 벗어난 경우
if ( fDistance2 >= m_fBindingDistance2 )
{
// 재계산 플래그가 없다면, 부모의 크기가 재계산되어야 한다.
if ( !m_pParent->HasSphereNodeFlag( SNF_RECOMPUTE ) )
{
m_pTree->AddRecompute( m_pParent );
}
// 부모와의 연결을 끊고, 해당 Root 노드에 연결한다.
Unlink();
m_pTree->AddIntegrate( this );
}
}
}
void
CCharSphereNode::NewPos( float fX, float fY, float fZ )
{
NewPos( Position(fX, fY, fZ) );
}
void
CCharSphereNode::NewPosRadius( const Position& Pos, float fRadius )
{
// 새로운 좌표 설정
m_Center = Pos;
// 부모가 있고, 재구성되어야 할 플래그가 없다면, 재구성을 할지를 판단한다.
if ( m_pParent && !HasSphereNodeFlag( SNF_INTEGRATE ) )
{
// 반지름이 변경 되었는지를 체크해서 변경되었다면,
// 반지름을 다시 설정하고, 바인딩 거리를 재계산한다.
if ( fRadius != GetRadius() )
{
SetRadius( fRadius );
ComputeBindingDistance( m_pParent );
}
// 부모와의 거리의 제곱값을 계산한다.
float fDistance2 = Distance2( m_pParent );
// 거리가 바인딩 거리를 벗어난 경우
if ( fDistance2 >= m_fBindingDistance2 )
{
// 재계산 플래그가 없다면, 부모의 크기가 재계산되어야 한다.
if ( !m_pParent->HasSphereNodeFlag( SNF_RECOMPUTE ) )
{
m_pTree->AddRecompute( m_pParent );
}
// 부모와의 연결을 끊고, 해당 Root 노드에 연결한다.
Unlink();
m_pTree->AddIntegrate( this );
}
// 자식이 부모의 바인딩 거리안에 있을 경우
else
{
// 부모의 바인딩 거리를 줄일수 있을수도 있기 때문에, 재계산을 한다.
if ( !m_pParent->HasSphereNodeFlag( SNF_RECOMPUTE ) )
{
m_pTree->AddRecompute( m_pParent );
}
}
}
}
void
CCharSphereNode::NewPosRadius( float fX, float fY, float fZ, float fRadius )
{
NewPosRadius( Position(fX, fY, fZ), fRadius );
}
float
CCharSphereNode::Distance2( const CCharSphereNode* pNode )
{
return static_cast<float>( m_Center.GetSquaredDistance( pNode->GetCenter() ) );
}
void
CCharSphereNode::ComputeBindingDistance( const CCharSphereNode* pParent )
{
m_fBindingDistance2 = pParent->GetRadius() - GetRadius();
if ( m_fBindingDistance2 <= 0 ) m_fBindingDistance2 = 0;
else m_fBindingDistance2 *= m_fBindingDistance2;
}
bool
CCharSphereNode::Recompute( float fGravy )
{
if ( !m_pChildren ) return true; // 제거 요망
if ( HasSphereNodeFlag( SNF_ROOT_NODE ) ) return false; // Root 는 재계산하지 않는다.
Position sumPos;
int iCount = 0;
// 자식들의 위치를 모두 더해서 평균을 구해서,
// 새로운 중심 좌표를 계산해 낸다.
CCharSphereNode* pChild = m_pChildren;
while ( pChild )
{
sumPos.m_fPointX += pChild->GetCenter().m_fPointX;
sumPos.m_fPointY += pChild->GetCenter().m_fPointY;
sumPos.m_fPointZ += pChild->GetCenter().m_fPointZ;
++iCount;
pChild = pChild->GetNextSibling();
}
if ( iCount )
{
float fRecip = 1.0f / float(iCount);
sumPos.m_fPointX *= fRecip;
sumPos.m_fPointY *= fRecip;
sumPos.m_fPointZ *= fRecip;
Position oldCenter = m_Center;
m_Center = sumPos; // 새로 구해준 중심 좌표로 설정
float fMaxRadius = 0;
// 자식들이 포함되는가 확인한다.
pChild = m_pChildren;
while ( pChild )
{
float fDistance2 = Distance2( pChild );
float fRadius = sqrtf( fDistance2 ) + pChild->GetRadius();
if ( fRadius > fMaxRadius )
{
fMaxRadius = fRadius;
if ( (fMaxRadius + fGravy) >= GetRadius() )
{
m_Center = oldCenter;
ClearShpereNodeFlag( SNF_RECOMPUTE );
return false;
}
}
pChild = pChild->GetNextSibling();
}
// 더 커진 반지름으로 재 설정
fMaxRadius += fGravy;
SetRadius( fMaxRadius );
// 자식들의 바인딩 거리를 재 계산
pChild = m_pChildren;
while ( pChild )
{
pChild->ComputeBindingDistance( this );
pChild = pChild->GetNextSibling();
}
}
ClearShpereNodeFlag( SNF_RECOMPUTE );
return false;
}
CCharSphereTree::CCharSphereTree( int iMaxSphereNode, float fRootSize, float fLeafSize, float fGravy ) :
m_fMaxRootSize(fRootSize), m_fMaxLeafSize(fLeafSize), m_fSuperSphereGravy(fGravy)
{
iMaxSphereNode *= 4;
m_Recompute = new CCharSphereNodeFifo( iMaxSphereNode );
m_Integrate = new CCharSphereNodeFifo( iMaxSphereNode );
// Root Tree 생성
Position rootPos;
m_pRoot = new CCharSphereNode();
m_pRoot->Init( this, rootPos, 65535, NULL );
m_pRoot->SetSphereNodeFlag( eSphereNodeFlag(SNF_ROOT_NODE | SNF_SUPERSPHERE | SNF_ROOT_TREE) );
// Leaf Tree 생성
m_pLeaf = new CCharSphereNode();
m_pLeaf->Init( this, rootPos, 16384, NULL );
m_pLeaf->SetSphereNodeFlag( eSphereNodeFlag(SNF_ROOT_NODE | SNF_SUPERSPHERE | SNF_LEAF_TREE) );
}
CCharSphereTree::~CCharSphereTree()
{
DeleteAllChildSphere( m_pRoot );
DeleteAllChildSphere( m_pLeaf );
SAFE_DELETE( m_pRoot );
SAFE_DELETE( m_pLeaf );
SAFE_DELETE( m_Recompute );
SAFE_DELETE( m_Integrate );
m_CharSphereMap.clear();
}
void
CCharSphereTree::Process()
{
// 재계산 되어야 할 목록에 있는 노드를 재계산한다.
// 만약 leaf node 가 부모를 벗어났다면, 부모가 재 구성되거나, 자식이 없다면, 제거되어야 한다.
if ( m_Recompute->GetCount() > 0 )
{
bool bKill;
CCharSphereNode* pTempNode = NULL;
int iCount = m_Recompute->GetCount();
for (int i=0; i<iCount; ++i)
{
pTempNode = m_Recompute->Pop();
if ( !pTempNode ) continue;
pTempNode->SetRecomputeFifo( NULL );
bKill = pTempNode->Recompute( m_fSuperSphereGravy );
if ( bKill )
{
DeleteSphere( pTempNode );
}
}
}
// 재구성 되어야 할 목록에 있는 노드를 재구성한다.
if ( m_Integrate->GetCount() > 0 )
{
CCharSphereNode* pTempNode = NULL;
int iCount = m_Integrate->GetCount();
for (int i=0; i<iCount; ++i)
{
pTempNode = m_Integrate->Pop();
if ( !pTempNode ) continue;
pTempNode->SetIntegrateFifo( NULL );
if ( pTempNode->HasSphereNodeFlag( SNF_ROOT_TREE ) )
Integrate( pTempNode, m_pRoot, m_fMaxRootSize ); // integrate this one single dude against the root node.
else
Integrate( pTempNode, m_pLeaf, m_fMaxLeafSize ); // integrate this one single dude against the root node.
}
}
}
bool
CCharSphereTree::AddCharacter( unsigned long dwCID, CCharacter* pCharacter, const Position& Pos )
{
CCharSphereNode* pNode = AddSphere( Pos, SphereConst::CHAR_RADIUS, NULL );
if ( pNode )
{
pNode->SetCID( dwCID );
pNode->SetCharacter( pCharacter );
pNode->SetSphereNodeFlag( SNF_ACTOR_NODE );
return m_CharSphereMap.insert( std::make_pair(dwCID, pNode) ).second;
}
return false;
}
bool
CCharSphereTree::DeleteCharacter( unsigned long dwCID )
{
CharSphereMap::iterator itr = m_CharSphereMap.find( dwCID );
if ( itr != m_CharSphereMap.end() )
{
CCharSphereNode* pNode = itr->second;
if ( pNode )
{
DeleteSphere( pNode );
}
m_CharSphereMap.erase( itr );
return true;
}
return false;
}
void
CCharSphereTree::MoveTo( unsigned long dwCID, const Position& NewPos )
{
CharSphereMap::iterator itr = m_CharSphereMap.find( dwCID );
if ( itr != m_CharSphereMap.end() )
{
CCharSphereNode* pNode = itr->second;
if ( pNode && pNode->GetCenter() != NewPos )
{
pNode->NewPos( NewPos );
}
}
}
CCharSphereNode*
CCharSphereTree::AddSphere( const Position& Pos, float fRadius, void* pLink, unsigned long dwFlag )
{
// 새로운 노드를 만든다.
CCharSphereNode* pNode = new CCharSphereNode();
assert( pNode );
if ( pNode )
{
// Root 와 Leaf 중에 한쪽의 멤버로 붙여주고, 재 구성 리스트에 넣는다.
if ( dwFlag & SNF_ROOT_TREE )
{
pNode->Init( this, Pos, fRadius, pLink );
pNode->SetSphereNodeFlag( SNF_ROOT_TREE );
AddIntegrate( pNode );
}
else
{
pNode->Init( this, Pos, fRadius, pLink );
pNode->SetSphereNodeFlag( SNF_LEAF_TREE );
AddIntegrate( pNode );
}
}
return pNode;
}
void
CCharSphereTree::DeleteSphere( CCharSphereNode* pNode )
{
// Root node 는 사용자가 지워준다.
if ( pNode->HasSphereNodeFlag( SNF_ROOT_NODE ) ) return;
// Leaf node tree 의 supersphere 는 링크된 root node tree 의 node 를 지워준다.
if ( pNode->HasSphereNodeFlag( SNF_SUPERSPHERE ) && pNode->HasSphereNodeFlag( SNF_LEAF_TREE) )
{
CCharSphereNode* pLink = (CCharSphereNode*) pNode->GetLink();
DeleteSphere( pLink );
}
pNode->Unlink();
SAFE_DELETE( pNode );
}
void
CCharSphereTree::DeleteAllChildSphere( CCharSphereNode* pRootNode )
{
CCharSphereNode* pTempNode = NULL;
CCharSphereNode* pChild = pRootNode->GetChildren();
while ( pChild )
{
if ( pChild->GetChildCount() )
{
DeleteAllChildSphere( pChild );
}
pTempNode = pChild;
pChild = pChild->GetNextSibling();
SAFE_DELETE( pTempNode );
}
}
void
CCharSphereTree::AddRecompute( CCharSphereNode* pNode )
{
if ( !pNode->HasSphereNodeFlag( SNF_RECOMPUTE ) )
{
if ( pNode->GetChildCount() )
{
pNode->SetSphereNodeFlag( SNF_RECOMPUTE );
CCharSphereNode** ppFifo = m_Recompute->Push( pNode );
pNode->SetRecomputeFifo( ppFifo );
}
else
{
DeleteSphere( pNode );
}
}
}
void
CCharSphereTree::AddIntegrate( CCharSphereNode* pNode )
{
if ( pNode->HasSphereNodeFlag( SNF_ROOT_TREE ) )
{
m_pRoot->AddChild( pNode );
}
else
{
m_pLeaf->AddChild( pNode );
}
pNode->SetSphereNodeFlag( SNF_INTEGRATE );
CCharSphereNode** ppFifo = m_Integrate->Push( pNode );
pNode->SetIntegrateFifo( ppFifo );
}
void
CCharSphereTree::Integrate( CCharSphereNode* pNode, CCharSphereNode* pSuperSphere, float fNodeSize )
{
// 재구성 단계 첫번째로 pNode 와 가장 가까이 있는 SuperSphere 를 찾는다.
CCharSphereNode* pSearch = pSuperSphere->GetChildren();
CCharSphereNode* pNearestNode1st = NULL; // pNode 를 완전히 둘러쌀수 있는 SuperSphere
CCharSphereNode* pNearestNode2nd = NULL; // pNode 를 추가하기 위해 약간 크기를 증가해야 하는 SuperSphere
float fNearDist1st2 = 1e9;
float fNearDist2nd2 = 1e9;
while ( pSearch )
{
if ( !pSearch->HasSphereNodeFlag( SNF_ROOT_NODE ) &&
pSearch->HasSphereNodeFlag( SNF_SUPERSPHERE ) &&
pSearch->GetChildCount() )
{
float fDistance2 = pNode->Distance2( pSearch );
if ( pNearestNode1st )
{
// 찾아 놓은 완전히 포함하는 SuperSphere 보다 더 가까운 녀석을 찾은 경우
if ( fDistance2 < fNearDist1st2 )
{
float fDist = sqrtf( fDistance2 ) + pNode->GetRadius();
if ( fDist <= pSearch->GetRadius() )
{
pNearestNode1st = pSearch;
fNearDist1st2 = fDistance2;
}
}
}
else
{
float fDist = sqrtf( fDistance2 ) + pNode->GetRadius() - pSearch->GetRadius();
if ( fDist < fNearDist2nd2 )
{
if ( fDist < 0 )
{
// 완전히 포함하는 SuperSphere 를 찾은 경우
pNearestNode1st = pSearch;
fNearDist1st2 = fDistance2;
}
else
{
// 완전히 포함하지는 못하지만, 반지름을 키워서 포함할 수 있는
// 가능성이 있는 SuperSphere 를 찾은 경우
pNearestNode2nd = pSearch;
fNearDist2nd2 = fDist;
}
}
}
}
pSearch = pSearch->GetNextSibling();
}
// pNode 를 완전히 포함할 수 있는 SuperSphere 를 찾은 경우
if ( pNearestNode1st )
{
// pNode 를 pNearestNode1st 의 자식으로 붙여주면 된다.
pNode->Unlink();
pNearestNode1st->AddChild( pNode );
pNearestNode1st->Recompute( m_fSuperSphereGravy );
pNode->ComputeBindingDistance( pNearestNode1st );
// 만약 leaf node 의 supersphere 라면, root tree 의 link node 또한 좌표와 크기를 갱신해준다.
if ( pNearestNode1st->HasSphereNodeFlag( SNF_LEAF_TREE ) )
{
CCharSphereNode* pLink = (CCharSphereNode*) pNearestNode1st->GetLink();
pLink->NewPosRadius( pNearestNode1st->GetCenter(), pNearestNode1st->GetRadius() );
}
}
else
{
bool bCreateNewSphere = true;
// 크기를 약간 키우면 pNode 를 포함할 수 있을만한 SuperSphere 를 찾은 경우
if ( pNearestNode2nd )
{
float fNewSize = fNearDist2nd2 + pNearestNode2nd->GetRadius() + m_fSuperSphereGravy;
if ( fNewSize <= fNodeSize )
{
pNode->Unlink();
pNearestNode2nd->SetRadius( fNewSize );
pNearestNode2nd->AddChild( pNode );
pNearestNode2nd->Recompute( m_fSuperSphereGravy );
pNode->ComputeBindingDistance( pNearestNode2nd );
if ( pNearestNode2nd->HasSphereNodeFlag( SNF_LEAF_TREE ) )
{
CCharSphereNode* pLink = (CCharSphereNode*) pNearestNode2nd->GetLink();
pLink->NewPosRadius( pNearestNode2nd->GetCenter(), pNearestNode2nd->GetRadius() );
}
bCreateNewSphere = false;
}
}
// 새로운 SuperSphere 를 만들어야 하는 경우
if ( bCreateNewSphere )
{
assert( pSuperSphere->HasSphereNodeFlag( SNF_ROOT_NODE ) );
pNode->Unlink();
CCharSphereNode* pParent = new CCharSphereNode();
assert( pParent );
pParent->Init( this, pNode->GetCenter(), pNode->GetRadius() + m_fSuperSphereGravy, NULL );
if ( pSuperSphere->HasSphereNodeFlag( SNF_ROOT_TREE ) )
{
pParent->SetSphereNodeFlag( eSphereNodeFlag(SNF_SUPERSPHERE | SNF_ROOT_TREE) );
}
else
{
pParent->SetSphereNodeFlag( eSphereNodeFlag(SNF_SUPERSPHERE | SNF_LEAF_TREE) );
}
pParent->AddChild( pNode );
pSuperSphere->AddChild( pParent );
pParent->Recompute( m_fSuperSphereGravy );
pNode->ComputeBindingDistance( pParent );
if ( pParent->HasSphereNodeFlag( SNF_LEAF_TREE ) )
{
// root node 에 link 를 생성해야 한다.
CCharSphereNode* pLink = AddSphere( pParent->GetCenter(), pParent->GetRadius(), pParent, SNF_ROOT_TREE );
pParent->SetLink( pLink );
}
}
}
pNode->ClearShpereNodeFlag( SNF_INTEGRATE );
}
void
CCharSphereNode::RangeTest( const Position& centerPos, float fDistance, ICharSphereTreeCallBack* pCallBack )
{
float fDist = static_cast<float>( m_Center.GetDistance( centerPos ) );
if ( (fDist - fDistance) > GetRadius() ) return;
if ( HasSphereNodeFlag( SNF_SUPERSPHERE ) )
{
CCharSphereNode* pNode = m_pChildren;
while ( pNode )
{
pNode->RangeTest( centerPos, fDistance, pCallBack );
pNode = pNode->GetNextSibling();
}
}
else
{
if ( HasSphereNodeFlag( SNF_ROOT_TREE ) )
{
CCharSphereNode* pLink = (CCharSphereNode*) GetLink();
if ( pLink )
{
pLink->RangeTest( centerPos, fDistance, pCallBack ) ;
}
}
else
{
pCallBack->RangeTestCallBack( centerPos, fDistance, this );
}
}
}
void
CCharSphereTree::RangeTest( const Position& centerPos, float fDistance, ICharSphereTreeCallBack* pCallBack )
{
m_pRoot->RangeTest( centerPos, fDistance, pCallBack );
}
void
CCharSphereNode::SendToRange( const Position& centerPos, float fDistance, const char* szPacket, unsigned long dwPacketSize, unsigned char cCMD_In )
{
float fDist = static_cast<float>( m_Center.GetDistance( centerPos ) );
if ( (fDist - fDistance) > GetRadius() ) return;
if ( HasSphereNodeFlag( SNF_SUPERSPHERE ) )
{
CCharSphereNode* pNode = m_pChildren;
while ( pNode )
{
pNode->SendToRange( centerPos, fDistance, szPacket, dwPacketSize, cCMD_In );
pNode = pNode->GetNextSibling();
}
}
else
{
if ( HasSphereNodeFlag( SNF_ROOT_TREE ) )
{
CCharSphereNode* pLink = (CCharSphereNode*) GetLink();
if ( pLink )
{
pLink->SendToRange( centerPos, fDistance, szPacket, dwPacketSize, cCMD_In ) ;
}
}
else
{
// Packet 전송
if (NULL != m_pCharacter)
{
CGameClientDispatch* lpDispatcher = m_pCharacter->GetDispatcher();
if (NULL != lpDispatcher)
{
lpDispatcher->GetSendStream().PutBuffer( szPacket, dwPacketSize, cCMD_In );
}
}
}
}
}
void
CCharSphereTree::SendToRange( const Position& centerPos, float fDistance, const char* szPacket, unsigned long dwPacketSize, unsigned char cCMD_In )
{
m_pRoot->SendToRange( centerPos, fDistance, szPacket, dwPacketSize, cCMD_In );
}

View File

@@ -0,0 +1,273 @@
#ifndef __CHARACTER_SPHERE_TREE_H__
#define __CHARACTER_SPHERE_TREE_H__
#include "Sphere.h"
#include "CharSphereTreeConstants.h"
using namespace SphereConst;
#include <map>
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if ((p)) { delete (p); (p) = NULL; } }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if ((p)) { delete [] (p); (p) = NULL; } }
#endif
//======================================================================================
struct Position;
class CCharacter;
class CSphere;
class CCharSphereNode;
class CCharSphereTree;
class CCharSphereNodeFifo;
class ICharSphereTreeCallBack;
//======================================================================================
class ICharSphereTreeCallBack
{
public:
virtual void RangeTestCallBack( const Position& centerPos, float fDistance, CCharSphereNode* pNode )
{
}
private:
};
//======================================================================================
class CCharSphereNode : public CSphere
{
public:
CCharSphereNode();
CCharSphereNode( CCharSphereTree* pTree, const Position& Pos, float fRadius, void* pLink );
void Init( CCharSphereTree* pTree, const Position& Pos, float fRadius, void* pLink );
// ===================================================================
// Flag 함수
void SetSphereNodeFlag( eSphereNodeFlag flag ) { m_dwFlag |= flag; }
void ClearShpereNodeFlag( eSphereNodeFlag flag ) { m_dwFlag &= ~flag; }
bool HasSphereNodeFlag( eSphereNodeFlag flag ) const
{
if ( m_dwFlag & flag ) return true;
return false;
}
// ===================================================================
// 캐릭터 관련 함수
void SetCID( unsigned long dwCID ) { m_dwCID = dwCID; }
unsigned long GetCID() const { return m_dwCID; }
void SetCharacter(CCharacter* pCharacter) { m_pCharacter = pCharacter; }
CCharacter* GetCharacter() const { return m_pCharacter; }
// ===================================================================
// 부모 & 자식 함수
void SetParent( CCharSphereNode* pParent ) { m_pParent = pParent; }
CCharSphereNode* GetParent() const { return m_pParent; }
void AddChild( CCharSphereNode* pChild );
void DeleteChild( CCharSphereNode* pChild );
CCharSphereNode* GetChildren() const { return m_pChildren; }
int GetChildCount() const { return m_iChildCount; }
// ===================================================================
// 같은 레벨의 형제 함수
void SetPrevSibling( CCharSphereNode* pNode ) { m_pPrevSibling = pNode; }
void SetNextSibling( CCharSphereNode* pNode ) { m_pNextSibling = pNode; }
CCharSphereNode* GetPrevSibling() const { return m_pPrevSibling; }
CCharSphereNode* GetNextSibling() const { return m_pNextSibling; }
// ===================================================================
// Fifo 포인터 관리 함수
void SetRecomputeFifo( CCharSphereNode** ppFifo ) { m_ppRecomuteFifo = ppFifo; }
void SetIntegrateFifo( CCharSphereNode** ppFifo ) { m_ppIntegrateFifo = ppFifo; }
// ===================================================================
// 부모와 자식 모두의 연결을 끊는 함수 (실제로는 부모와만 연결을 끊는다.)
void Unlink();
// ===================================================================
// Root tree node 의 Link ( Leaf tree 의 Root 가 아닌 SuperSphere node 가 가진다 )
void SetLink( void* pLink ) { m_pLink = pLink; }
void* GetLink() const { return m_pLink; }
// ===================================================================
// 좌표 변경 함수
void NewPos( const Position& Pos );
void NewPos( float fX, float fY, float fZ );
void NewPosRadius( const Position& Pos, float fRadius );
void NewPosRadius( float fX, float fY, float fZ, float fRadius );
// ===================================================================
// 거리 및 바인딩거리 계산 함수
float Distance2( const CCharSphereNode* pNode );
void ComputeBindingDistance( const CCharSphereNode* pParent );
// ===================================================================
// 크기 재계산 함수 ( true 리턴시에는 제거해야함 )
bool Recompute( float fGravy );
// ===================================================================
// 범위 테스트용 함수
void RangeTest( const Position& centerPos, float fDistance, ICharSphereTreeCallBack* pCallBack );
void SendToRange( const Position& centerPos, float fDistance, const char* szPacket,
unsigned long dwPacketSize, unsigned char cCMD_In );
protected:
private:
unsigned long m_dwCID;
CCharacter* m_pCharacter;
CCharSphereNode* m_pParent;
CCharSphereNode* m_pChildren;
CCharSphereNode* m_pPrevSibling;
CCharSphereNode* m_pNextSibling;
CCharSphereNode** m_ppRecomuteFifo; // Recompute Fifo 내의 위치 포인터
CCharSphereNode** m_ppIntegrateFifo; // Integrate Fifo 내의 위치 포인터
int m_iChildCount;
unsigned long m_dwFlag;
float m_fBindingDistance2;
void* m_pLink;
CCharSphereTree* m_pTree;
};
//======================================================================================
class CCharSphereTree
{
public:
CCharSphereTree( int iMaxSphereNode, float fRootSize, float fLeafSize, float fGravy );
virtual ~CCharSphereTree();
typedef std::map< unsigned long, CCharSphereNode* > CharSphereMap;
static CCharSphereTree& GetInstance();
// ===================================================================
// Tree 의 Node 를 재계산하고 재구성하는 처리 함수
void Process();
// ===================================================================
// 캐릭터 관련 함수
bool AddCharacter( unsigned long dwCID, CCharacter* pCharacter, const Position& Pos ) ;
bool DeleteCharacter( unsigned long dwCID );
void MoveTo( unsigned long dwCID, const Position& NewPos );
// ===================================================================
// CCharSphereNode 를 생성(캐릭터 제외)해서 재구성하는 함수 와 삭제하는 함수
CCharSphereNode* AddSphere( const Position& Pos, float fRadius, void* pLink, unsigned long dwFlag = SNF_LEAF_TREE );
void DeleteSphere( CCharSphereNode* pNode );
// ===================================================================
// 재계산, 재구성 리스트에 Node 추가 함수
void AddRecompute( CCharSphereNode* pNode );
void AddIntegrate( CCharSphereNode* pNode );
// ===================================================================
// Tree 를 재구성하는 함수
void Integrate( CCharSphereNode* pNode, CCharSphereNode* pSuperSphere, float fNodeSize );
// ===================================================================
// 범위 테스트용 함수
void RangeTest( const Position& centerPos, float fDistance, ICharSphereTreeCallBack* pCallBack );
void SendToRange( const Position& centerPos, float fDistance, const char* szPacket,
unsigned long dwPacketSize, unsigned char cCMD_In );
protected:
// ===================================================================
// 모든 자식 Node 를 메모리 해제하는 함수
void DeleteAllChildSphere( CCharSphereNode* pRootNode );
private:
CCharSphereNode* m_pRoot;
CCharSphereNode* m_pLeaf;
CCharSphereNodeFifo* m_Recompute;
CCharSphereNodeFifo* m_Integrate;
float m_fMaxRootSize;
float m_fMaxLeafSize;
float m_fSuperSphereGravy;
CharSphereMap m_CharSphereMap;
};
//======================================================================================
class CCharSphereNodeFifo
{
public:
CCharSphereNodeFifo( int iSize )
{
m_iCount = 0;
m_iStackPointer = 0;
m_iBottom = 0;
m_iSize = iSize;
m_ppFifo = new CCharSphereNode *[ m_iSize ];
};
~CCharSphereNodeFifo()
{
SAFE_DELETE_ARRAY( m_ppFifo );
};
CCharSphereNode** Push( CCharSphereNode* pNode )
{
m_iCount++;
CCharSphereNode** ret = &m_ppFifo[ m_iStackPointer ];
m_ppFifo[ m_iStackPointer ] = pNode;
++m_iStackPointer;
if ( m_iStackPointer == m_iSize ) m_iStackPointer = 0;
return ret;
};
CCharSphereNode* Pop()
{
while ( m_iStackPointer != m_iBottom )
{
--m_iCount;
CCharSphereNode* ret = m_ppFifo[ m_iBottom ];
++m_iBottom;
if ( m_iBottom == m_iSize ) m_iBottom = 0;
if ( ret ) return ret;
}
return NULL;
}
bool Flush( CCharSphereNode* pNode )
{
if ( m_iStackPointer == m_iBottom ) return false;
int i = m_iBottom;
while ( i != m_iStackPointer )
{
if ( m_ppFifo[i] == pNode )
{
m_ppFifo[i] = NULL;
return true;
}
i++;
if ( i == m_iSize ) i = 0;
}
return false;
};
int GetCount(void) const { return m_iCount; }
private:
int m_iCount;
int m_iStackPointer;
int m_iBottom;
int m_iSize;
CCharSphereNode** m_ppFifo;
};
#endif __CHARACTER_SPHERE_TREE_H__

View File

@@ -0,0 +1,34 @@
#ifndef __SPHERE_TREE_CONST_H__
#define __SPHERE_TREE_CONST_H__
namespace SphereConst
{
enum eSphereNodeFlag
{
SNF_ROOT_NODE = (1<<0), // this is the root node
SNF_SUPERSPHERE = (1<<1), // this is a supersphere, allocated and deleted by us
SNF_ACTOR_NODE = (1<<2), // this is real actor node
SNF_ROOT_TREE = (1<<3), // member of the root tree
SNF_LEAF_TREE = (1<<4), // member of the leaf node tree
SNF_RECOMPUTE = (1<<5), // needs recomputed bounding sphere
SNF_INTEGRATE = (1<<6) // needs to be reintegrated into tree
};
enum eViewState
{
VS_INSIDE, // completely inside the frustum.
VS_PARTIAL, // partially inside and partially outside the frustum.
VS_OUTSIDE // completely outside the frustum
};
enum eConst
{
CHAR_RADIUS = 2, // 캐릭터 반경 2m
MAX_SPHERE_NODE = 2000, // MAX 2000 명까지
DEFAULT_ROOT_SIZE = 256, // Root node 의 사이즈
DEFAULT_LEAF_SIZE = 64, // Leaf node 의 사이즈
DEFAULT_GRAVY = 15 // 부모원과 자식원의 반지름 차
};
};
#endif __SPHERE_TREE_CONST_H__

View File

@@ -0,0 +1,214 @@
#ifndef __SPHERE_H__
#define __SPHERE_H__
#include <math.h>
#include <Creature/CreatureStructure.h>
//======================================================================================
// 3차원 좌표 구조체
/*
#ifndef EPSILON
#define EPSILON 0.001
#endif
struct sVector3
{
union
{
struct
{
float x;
float y;
float z;
};
float v[3];
};
sVector3()
{
x = 0;
y = 0;
z = 0;
}
sVector3( float fX, float fY, float fZ )
{
x = fX;
y = fY;
z = fZ;
}
float Length() const
{
return sqrtf( x*x + y*y + z*z );
}
float Distance( const sVector3& inPos ) const
{
sVector3 tempVector( inPos.x - x, inPos.y - y, inPos.z - z );
return tempVector.Length();
}
float Distance2( const sVector3& inPos ) const
{
return ( (inPos.x - x) * (inPos.x - x) + (inPos.y - y) * (inPos.y - y) + (inPos.z - z) * (inPos.z - z) );
}
bool operator == ( const sVector3& inPos ) const
{
if ( fabs(x - inPos.x) <= EPSILON && fabs(y - inPos.y) <= EPSILON && fabs(z - inPos.z) <= EPSILON )
{
return true;
}
return false;
}
bool operator != ( const sVector3& inPos ) const
{
if ( fabs(x - inPos.x) > EPSILON || fabs(y - inPos.y) > EPSILON || fabs(z - inPos.z) > EPSILON )
{
return true;
}
return false;
}
};
*/
//======================================================================================
// 기본 구 클래스
class CSphere
{
public:
CSphere();
CSphere( float fX, float fY, float fZ, float fRadius );
CSphere( const Position& inPos, float fRadius );
// ===============================================================
void Set( float fX, float fY, float fZ, float fRadius );
void Set( const Position& inPos, float fRadius );
void SetRadius( float fRadius );
float GetX() const { return m_Center.m_fPointX; }
float GetY() const { return m_Center.m_fPointY; }
float GetZ() const { return m_Center.m_fPointZ; }
const Position& GetCenter() const { return m_Center; }
float GetRadius() const { return m_fRadius; }
float GetRadius2() const { return m_fRadius2; }
// ===============================================================
// 3차원 좌표가 구안에 있는지 검사
// 구의 반지름 + fDistance 안에 있는지 검사를 한다.
bool InSphere( float fX, float fY, float fZ, float fDistance );
bool InSphere( const Position& inPos, float fDistance );
// 2차원 좌표가 구안에 있는지 검사
// 구의 반지름 + fDistance 안에 있는지 검사를 한다.
bool InSphereXY( float fX, float fY, float fDistance );
bool InSphereXY( const Position& inPos, float fDistance );
protected:
Position m_Center; // 구의 중심 좌표
private:
float m_fRadius; // 구의 반지름
float m_fRadius2; // 구의 반지름 제곲 값
};
inline
CSphere::CSphere() :
m_fRadius(0), m_fRadius2(0)
{
}
inline
CSphere::CSphere( float fX, float fY, float fZ, float fRadius ) :
m_fRadius(fRadius), m_fRadius2(fRadius * fRadius)
{
}
inline
CSphere::CSphere( const Position& inPos, float fRadius ) :
m_Center(inPos), m_fRadius(fRadius), m_fRadius2(fRadius * fRadius)
{
}
inline void
CSphere::Set( float fX, float fY, float fZ, float fRadius )
{
m_Center.m_fPointX = fX;
m_Center.m_fPointY = fY;
m_Center.m_fPointZ = fZ;
m_fRadius = fRadius;
m_fRadius2 = fRadius * fRadius;
}
inline void
CSphere::Set( const Position& inPos, float fRadius )
{
m_Center = inPos;
m_fRadius = fRadius;
m_fRadius2 = fRadius * fRadius;
}
inline void
CSphere::SetRadius( float fRadius )
{
m_fRadius = fRadius;
m_fRadius2 = fRadius * fRadius;
}
inline bool
CSphere::InSphere( float fX, float fY, float fZ, float fDistance )
{
float dx = fX - m_Center.m_fPointX;
float dy = fY - m_Center.m_fPointY;
float dz = fZ - m_Center.m_fPointZ;
float dist = sqrtf( dx*dx + dy*dy + dz*dz );
if ( dist < (m_fRadius + fDistance) ) return true;
return false;
}
inline bool
CSphere::InSphere( const Position& inPos, float fDistance )
{
float dx = inPos.m_fPointX - m_Center.m_fPointX;
float dy = inPos.m_fPointY - m_Center.m_fPointY;
float dz = inPos.m_fPointZ - m_Center.m_fPointZ;
float dist = sqrtf( dx*dx + dy*dy + dz*dz );
if ( dist < (m_fRadius + fDistance) ) return true;
return false;
}
inline bool
CSphere::InSphereXY( float fX, float fY, float fDistance )
{
float dx = fX - m_Center.m_fPointX;
float dy = fY - m_Center.m_fPointY;
float dist = sqrtf( dx*dx + dy*dy );
if ( dist < (m_fRadius + fDistance) ) return true;
return false;
}
inline bool
CSphere::InSphereXY( const Position& inPos, float fDistance )
{
float dx = inPos.m_fPointX - m_Center.m_fPointX;
float dy = inPos.m_fPointY - m_Center.m_fPointY;
float dist = sqrtf( dx*dx + dy*dy );
if ( dist < (m_fRadius + fDistance) ) return true;
return false;
}
#endif __SPHERE_H__