summaryrefslogtreecommitdiffstats
path: root/source/cEntity.cpp
diff options
context:
space:
mode:
authorfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-10-03 20:41:19 +0200
committerfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-10-03 20:41:19 +0200
commit386d58b5862d8b76925c6523721594887606e82a (patch)
treeef073e7a843f4b75a4008d4b7383f7cdf08ceee5 /source/cEntity.cpp
parentVisual Studio 2010 solution and project files (diff)
downloadcuberite-386d58b5862d8b76925c6523721594887606e82a.tar
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.gz
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.bz2
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.lz
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.xz
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.zst
cuberite-386d58b5862d8b76925c6523721594887606e82a.zip
Diffstat (limited to 'source/cEntity.cpp')
-rw-r--r--source/cEntity.cpp283
1 files changed, 283 insertions, 0 deletions
diff --git a/source/cEntity.cpp b/source/cEntity.cpp
new file mode 100644
index 000000000..3b62bec9c
--- /dev/null
+++ b/source/cEntity.cpp
@@ -0,0 +1,283 @@
+#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_EntityCount++;
+ m_UniqueID = m_EntityCount;
+}
+
+cEntity::~cEntity()
+{
+ delete m_Referencers;
+ delete m_References;
+ cChunk* Chunk = cRoot::Get()->GetWorld()->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()
+{
+ cRoot::Get()->GetWorld()->AddEntity( this );
+
+ cWorld::BlockToChunk( (int)m_Pos->x, (int)m_Pos->y, (int)m_Pos->z, m_ChunkX, m_ChunkY, m_ChunkZ );
+ cChunk* Chunk = cRoot::Get()->GetWorld()->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()
+{
+ 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 )
+ {
+ cWorld* World = cRoot::Get()->GetWorld();
+ LOG("From %i %i To %i %i", m_ChunkX, m_ChunkZ, ChunkX, ChunkZ );
+ cChunk* Chunk = 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 = 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 );
+}