1
0
cuberite-2a/source/cEntity.cpp
faketruth b5b920deda You can now run multiple worlds by defining them in settings.ini . However there's no way to change worlds on the fly yet
Players are now stored in separate folder /players instead of in the world folder (!so move the folder!)
Fixed a memory leak/error in cPickup.cpp
Multiple worlds are stored in cRoot
cClientHandle lists are taken out of cWorld and now stored in cServer
Worlds now have names to distinguish them by
Some functions in the Core plugin now distinguish between worlds

git-svn-id: http://mc-server.googlecode.com/svn/trunk@40 0a769ca7-a7f5-676a-18bf-c427514a06d6
2011-11-01 21:57:08 +00:00

290 lines
6.9 KiB
C++

#include "cEntity.h"
#include "cWorld.h"
#include "cChunk.h"
#include "cMCLogger.h"
#include "cServer.h"
#include "cRoot.h"
#include "Vector3d.h"
#include "Vector3f.h"
#include "Matrix4f.h"
#include "cReferenceManager.h"
#include "cClientHandle.h"
#include "packets/cPacket_DestroyEntity.h"
int cEntity::m_EntityCount = 0;
cEntity::cEntity(const double & a_X, const double & a_Y, const double & a_Z)
: m_UniqueID( 0 )
, m_Referencers( new cReferenceManager( cReferenceManager::RFMNGR_REFERENCERS ) )
, m_References( new cReferenceManager( cReferenceManager::RFMNGR_REFERENCES ) )
, m_ChunkX( 0 )
, m_ChunkY( 0 )
, m_ChunkZ( 0 )
, m_Pos( new Vector3d( a_X, a_Y, a_Z ) )
, m_bDirtyPosition( true )
, m_Rot( new Vector3f() )
, m_bDirtyOrientation( true )
, m_bDestroyed( false )
, m_EntityType( E_ENTITY )
, m_World( 0 )
{
m_EntityCount++;
m_UniqueID = m_EntityCount;
}
cEntity::~cEntity()
{
delete m_Referencers;
delete m_References;
if( m_World )
{
cChunk* Chunk = m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ );
if( Chunk )
{
cPacket_DestroyEntity DestroyEntity( this );
Chunk->Broadcast( DestroyEntity );
Chunk->RemoveEntity( *this );
}
}
delete m_Pos;
delete m_Rot;
}
void cEntity::Initialize( cWorld* a_World )
{
m_World = a_World;
m_World->AddEntity( this );
cWorld::BlockToChunk( (int)m_Pos->x, (int)m_Pos->y, (int)m_Pos->z, m_ChunkX, m_ChunkY, m_ChunkZ );
cChunk* Chunk = m_World->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
if( Chunk )
{
//LOG("Adding entity %i to chunk %i %i %i", m_UniqueID, Chunk->GetPosX(), Chunk->GetPosY(), Chunk->GetPosZ() );
Chunk->AddEntity( *this );
}
}
void cEntity::WrapRotation()
{
while(m_Rot->x > 180.f) m_Rot->x-=360.f; // Wrap it
while(m_Rot->x < -180.f) m_Rot->x+=360.f;
while(m_Rot->y > 180.f) m_Rot->y-=360.f;
while(m_Rot->y < -180.f) m_Rot->y+=360.f;
}
void cEntity::MoveToCorrectChunk()
{
if( !m_World ) return; // Entity needs a world to move to a chunk
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
cWorld::BlockToChunk( (int)m_Pos->x, (int)m_Pos->y, (int)m_Pos->z, ChunkX, ChunkY, ChunkZ );
if( m_ChunkX != ChunkX || m_ChunkY != ChunkY || m_ChunkZ != ChunkZ )
{
LOG("From %i %i To %i %i", m_ChunkX, m_ChunkZ, ChunkX, ChunkZ );
cChunk* Chunk = m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ );
typedef std::list< cClientHandle* > ClientList;
ClientList BeforeClients;
if( Chunk )
{
Chunk->RemoveEntity( *this );
BeforeClients = Chunk->GetClients();
}
m_ChunkX = ChunkX; m_ChunkY = ChunkY; m_ChunkZ = ChunkZ;
cChunk* NewChunk = m_World->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
ClientList AfterClients;
if( NewChunk )
{
NewChunk->AddEntity( *this );
AfterClients = NewChunk->GetClients();
}
/********************
* I reaalllyyyy don't like this piece of code, but it's needed I guess (maybe there's a way to optimize this)
**/
// Now compare clients before with after
for( ClientList::iterator itr = BeforeClients.begin(); itr != BeforeClients.end(); ++itr )
{
bool bFound = false;
for( ClientList::iterator itr2 = AfterClients.begin(); itr2 != AfterClients.end(); ++itr2 )
{
if( *itr2 == *itr )
{
bFound = true;
break;
}
}
if( !bFound ) // Client was in old chunk, but not new, so destroy on that client
{
cPacket_DestroyEntity DestroyEntity( this );
(*itr)->Send( DestroyEntity );
}
}
// Now compare clients after with before
for( ClientList::iterator itr = AfterClients.begin(); itr != AfterClients.end(); ++itr )
{
bool bFound = false;
for( ClientList::iterator itr2 = BeforeClients.begin(); itr2 != BeforeClients.end(); ++itr2 )
{
if( *itr2 == *itr )
{
bFound = true;
break;
}
}
if( !bFound ) // Client is in the new chunk, but not in old, so spawn on the client
{
SpawnOn( *itr );
}
}
}
}
CLASS_DEF_GETCLASS( cEntity );
bool cEntity::IsA( const char* a_EntityType )
{
//LOG("IsA( cEntity ) : %s", a_EntityType);
if( strcmp( a_EntityType, "cEntity" ) == 0 ) return true;
return false;
}
//////////////////////////////////////////////////////////////////////////
// Set orientations
void cEntity::SetRot( const Vector3f & a_Rot )
{
*m_Rot = a_Rot;
m_bDirtyOrientation = true;
}
void cEntity::SetRotation( float a_Rotation )
{
m_Rot->x = a_Rotation;
m_bDirtyOrientation = true;
}
void cEntity::SetPitch( float a_Pitch )
{
m_Rot->y = a_Pitch;
m_bDirtyOrientation = true;
}
void cEntity::SetRoll( float a_Roll )
{
m_Rot->z = a_Roll;
m_bDirtyOrientation = true;
}
//////////////////////////////////////////////////////////////////////////
// Get orientations
const Vector3f & cEntity::GetRot()
{
return *m_Rot;
}
float cEntity::GetRotation()
{
return m_Rot->x;
}
float cEntity::GetPitch()
{
return m_Rot->y;
}
float cEntity::GetRoll()
{
return m_Rot->z;
}
//////////////////////////////////////////////////////////////////////////
// Get look vector (this is NOT a rotation!)
Vector3f cEntity::GetLookVector()
{
Matrix4f m;
m.Init( Vector3f(), 0, m_Rot->x, -m_Rot->y );
Vector3f Look = m.Transform( Vector3f(0, 0, 1) );
LOG("Look: %0.1f %0.1f %0.1f", Look.x, Look.y, Look.z );
return Look;
}
//////////////////////////////////////////////////////////////////////////
// Set position
void cEntity::SetPosition( const Vector3d & a_Pos )
{
*m_Pos = a_Pos;
MoveToCorrectChunk();
m_bDirtyPosition = true;
}
void cEntity::SetPosition( const double & a_PosX, const double & a_PosY, const double & a_PosZ )
{
m_Pos->Set( a_PosX, a_PosY, a_PosZ );
MoveToCorrectChunk();
m_bDirtyPosition = true;
}
void cEntity::SetPosX( const double & a_PosX )
{
m_Pos->x = a_PosX;
MoveToCorrectChunk();
m_bDirtyPosition = true;
}
void cEntity::SetPosY( const double & a_PosY )
{
m_Pos->y = a_PosY;
MoveToCorrectChunk();
m_bDirtyPosition = true;
}
void cEntity::SetPosZ( const double & a_PosZ )
{
m_Pos->z = a_PosZ;
MoveToCorrectChunk();
m_bDirtyPosition = true;
}
//////////////////////////////////////////////////////////////////////////
// Get position
const Vector3d & cEntity::GetPosition()
{
return *m_Pos;
}
const double & cEntity::GetPosX()
{
return m_Pos->x;
}
const double & cEntity::GetPosY()
{
return m_Pos->y;
}
const double & cEntity::GetPosZ()
{
return m_Pos->z;
}
//////////////////////////////////////////////////////////////////////////
// Reference stuffs
void cEntity::AddReference( cEntity*& a_EntityPtr )
{
m_References->AddReference( a_EntityPtr );
a_EntityPtr->ReferencedBy( a_EntityPtr );
}
void cEntity::ReferencedBy( cEntity*& a_EntityPtr )
{
m_Referencers->AddReference( a_EntityPtr );
}
void cEntity::Dereference( cEntity*& a_EntityPtr )
{
m_Referencers->Dereference( a_EntityPtr );
}