diff --git a/VC2010/MCServer.vcxproj b/VC2010/MCServer.vcxproj
index 1186a6b5c..4c0a3cca7 100644
--- a/VC2010/MCServer.vcxproj
+++ b/VC2010/MCServer.vcxproj
@@ -522,6 +522,7 @@
+
diff --git a/VC2010/MCServer.vcxproj.filters b/VC2010/MCServer.vcxproj.filters
index 203933c48..4ed54000a 100644
--- a/VC2010/MCServer.vcxproj.filters
+++ b/VC2010/MCServer.vcxproj.filters
@@ -448,6 +448,9 @@
{69e6a927-8e49-4d39-af88-f587d17bb8a3}
+
+ {9bd7a65c-b60f-4905-ae2b-7c3c7586eaef}
+
@@ -1371,6 +1374,9 @@
cInventory\cSurvivalInventory
+
+ !Smart_Pointers
+
diff --git a/source/Vector3d.h b/source/Vector3d.h
index 84b04fce7..f93c2c763 100644
--- a/source/Vector3d.h
+++ b/source/Vector3d.h
@@ -22,6 +22,8 @@ public: //tolua_export
inline double Dot( const Vector3d & a_V ) const { return x * a_V.x + y * a_V.y + z * a_V.z; } //tolua_export
inline Vector3d Cross( const Vector3d & v ) const { return Vector3d( y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x ); } //tolua_export
+ inline bool Equals( const Vector3d & v ) const { return (x == v.x && y == v.y && z == v.z ); } //tolua_export
+
void operator += ( const Vector3d& a_V ) { x += a_V.x; y += a_V.y; z += a_V.z; }
void operator += ( Vector3d* a_V ) { x += a_V->x; y += a_V->y; z += a_V->z; }
void operator -= ( const Vector3d& a_V ) { x -= a_V.x; y -= a_V.y; z -= a_V.z; }
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index 47e92555f..3af1b0ff3 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -62,6 +62,7 @@ struct cChunk::sChunkState
sChunkState()
: TotalReferencesEver( 0 )
, MinusReferences( 0 )
+ , NumRefs( 0 )
{}
FurnaceEntityList TickBlockEntities;
@@ -79,6 +80,7 @@ struct cChunk::sChunkState
ReferenceMap References;
int MinusReferences; // References.size() - MinusReferences = Actual amount of references. This is due to removal of reference without an ID (don't know which to remove, so remove none)
int TotalReferencesEver; // For creating a unique reference ID
+ int NumRefs;
};
cChunk::~cChunk()
@@ -541,8 +543,8 @@ void cChunk::SpreadLight(char* a_LightBuffer)
bool bCalcLeft, bCalcRight, bCalcFront, bCalcBack;
bCalcLeft = bCalcRight = bCalcFront = bCalcBack = false;
// Spread to neighbour chunks X-axis
- cChunk* LeftChunk = m_World->GetChunkUnreliable( m_PosX-1, m_PosY, m_PosZ );
- cChunk* RightChunk = m_World->GetChunkUnreliable( m_PosX+1, m_PosY, m_PosZ );
+ ptr_cChunk LeftChunk = m_World->GetChunkUnreliable( m_PosX-1, m_PosY, m_PosZ );
+ ptr_cChunk RightChunk = m_World->GetChunkUnreliable( m_PosX+1, m_PosY, m_PosZ );
char* LeftSky = 0, *RightSky = 0;
if(LeftChunk) LeftSky = (a_LightBuffer==m_BlockSkyLight)?LeftChunk->pGetSkyLight():LeftChunk->pGetLight();
if(RightChunk) RightSky = (a_LightBuffer==m_BlockSkyLight)?RightChunk->pGetSkyLight():RightChunk->pGetLight();
@@ -579,8 +581,8 @@ void cChunk::SpreadLight(char* a_LightBuffer)
}
// Spread to neighbour chunks Z-axis
- cChunk* FrontChunk = m_World->GetChunkUnreliable( m_PosX, m_PosY, m_PosZ-1 );
- cChunk* BackChunk = m_World->GetChunkUnreliable( m_PosX, m_PosY, m_PosZ+1 );
+ ptr_cChunk FrontChunk = m_World->GetChunkUnreliable( m_PosX, m_PosY, m_PosZ-1 );
+ ptr_cChunk BackChunk = m_World->GetChunkUnreliable( m_PosX, m_PosY, m_PosZ+1 );
char* FrontSky = 0, *BackSky = 0;
if(FrontChunk) FrontSky = (a_LightBuffer==m_BlockSkyLight)?FrontChunk->pGetSkyLight():FrontChunk->pGetLight();
if(BackChunk) BackSky = (a_LightBuffer==m_BlockSkyLight)?BackChunk->pGetSkyLight():BackChunk->pGetLight();
@@ -1177,60 +1179,28 @@ void cChunk::PositionToWorldPosition(int a_ChunkX, int a_ChunkY, int a_ChunkZ, i
a_Z = m_PosZ * 16 + a_ChunkZ;
}
-int cChunk::AddReference( const char* a_Info /* = 0 */ )
+void cChunk::AddReference()
{
m_pState->ReferenceCriticalSection.Lock();
-
- m_pState->TotalReferencesEver++;
-
- std::string Info;
- if( a_Info ) Info = a_Info;
-
- m_pState->References[ m_pState->TotalReferencesEver ] = Info;
-
- int ID = m_pState->TotalReferencesEver;
+ m_pState->NumRefs++;
m_pState->ReferenceCriticalSection.Unlock();
- return ID;
}
-void cChunk::RemoveReference( int a_ID )
+void cChunk::RemoveReference()
{
m_pState->ReferenceCriticalSection.Lock();
-
- if( a_ID > -1 ) // Remove reference with an ID
+ m_pState->NumRefs--;
+ if( m_pState->NumRefs < 0 )
{
- bool bFound = false;
- for( ReferenceMap::iterator itr = m_pState->References.begin(); itr != m_pState->References.end(); ++itr )
- {
- if( itr->first == a_ID )
- {
- bFound = true;
- m_pState->References.erase( itr );
- break;
- }
- }
-
- if( !bFound )
- {
- LOGWARN("WARNING: cChunk: Tried to remove reference %i but it could not be found! May cause memory leak", a_ID );
- }
+ LOGWARN("WARNING: cChunk: Tried to remove reference, but the chunk is not referenced!");
}
- else // No ID so add one to MinusReferences
- {
- m_pState->MinusReferences++;
- if( (int)m_pState->References.size() - m_pState->MinusReferences < 0 )
- {
- LOGWARN("WARNING: cChunk: Tried to remove reference %i, but the chunk is not referenced!", a_ID);
- }
- }
-
m_pState->ReferenceCriticalSection.Unlock();
}
int cChunk::GetReferenceCount()
{
m_pState->ReferenceCriticalSection.Unlock();
- int Refs = (int)m_pState->References.size() - m_pState->MinusReferences;
+ int Refs = m_pState->NumRefs;
m_pState->ReferenceCriticalSection.Lock();
return Refs;
}
diff --git a/source/cChunk.h b/source/cChunk.h
index 8555e01cf..15577d372 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -102,8 +102,8 @@ public:
static const int c_BlockDataSize = c_NumBlocks * 2 + (c_NumBlocks/2); // 2.5 * numblocks
// Reference counting
- int AddReference( const char* a_Info = 0 ); // a_Info is for debugging
- void RemoveReference( int a_ID = -1 );
+ void AddReference();
+ void RemoveReference();
int GetReferenceCount();
private:
struct sChunkState;
diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp
index d05fd4a43..fb23096d8 100644
--- a/source/cChunkMap.cpp
+++ b/source/cChunkMap.cpp
@@ -465,7 +465,7 @@ void cChunkMap::UnloadUnusedChunks()
if( Chunk && Chunk->GetClients().size() == 0 && Chunk->GetReferenceCount() <= 0 )
{
Chunk->SaveToDisk();
- World->RemoveSpread( Chunk );
+ World->RemoveSpread( ptr_cChunk( Chunk ) );
RemoveChunk( Chunk );
delete Chunk;
}
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index 891140630..46669848e 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -113,6 +113,8 @@ struct cClientHandle::sClientHandleState
cCriticalSection SocketCriticalSection;
cSemaphore* pSemaphore;
+ Vector3d ConfirmPosition;
+
cPacket* PacketMap[256];
};
@@ -126,6 +128,7 @@ cClientHandle::cClientHandle(const cSocket & a_Socket)
, m_bSendLoginResponse( false )
, m_pState( new sClientHandleState )
, m_Ping(1000)
+ , m_bPositionConfirmed( false )
{
LOG("cClientHandle::cClientHandle");
@@ -382,6 +385,7 @@ void cClientHandle::StreamChunksSmart( cChunk** a_Chunks, unsigned int a_NumChun
{
a_Chunks[ClosestIdx]->Send( this );
a_Chunks[ClosestIdx]->AddClient( this );
+ //LOGINFO("CCC: Sending chunk %i %i", a_Chunks[ClosestIdx]->GetPosX(), a_Chunks[ClosestIdx]->GetPosZ() );
a_Chunks[ClosestIdx] = 0;
}
}
@@ -526,6 +530,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
StreamChunks();
// Send position
+ m_pState->ConfirmPosition = m_Player->GetPosition();
Send( cPacket_PlayerMoveLook( m_Player ) );
}
break;
@@ -539,7 +544,32 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
break;
}
}
- else // m_bLoggedIn == true
+ else if( !m_bPositionConfirmed ) // m_bLoggedIn == true
+ {
+ switch( a_Packet->m_PacketID )
+ {
+ case E_PLAYERMOVELOOK:
+ {
+ cPacket_PlayerMoveLook* PacketData = reinterpret_cast(a_Packet);
+ Vector3d ReceivedPosition = Vector3d( PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ );
+
+ // Test the distance between points with a small/large enough value instead of comparing directly. Floating point inaccuracies might screw stuff up
+ if( ( ReceivedPosition - m_pState->ConfirmPosition ).SqrLength() < 1.0 )
+ {
+ // Test
+ if( ReceivedPosition.Equals( m_pState->ConfirmPosition ) )
+ {
+ LOGINFO("Exact position confirmed by client!");
+ }
+ m_bPositionConfirmed = true;
+ }
+ }
+ break;
+ }
+
+ }
+
+ if( m_bPositionConfirmed )
{
switch( a_Packet->m_PacketID )
{
@@ -1434,6 +1464,7 @@ void cClientHandle::SendThread( void *lpParam )
m_pState->SocketCriticalSection.Unlock();
break;
}
+ //LOG("Send packet: 0x%2x", Packet->m_PacketID );
bool bSuccess = Packet->Send( m_pState->Socket );
m_pState->SocketCriticalSection.Unlock();
if( !bSuccess )
@@ -1481,6 +1512,7 @@ void cClientHandle::ReceiveThread( void *lpParam )
}
else
{
+ //LOG("Recv packet: 0x%2x", (unsigned char)temp );
cPacket* pPacket = self->m_pState->PacketMap[ (unsigned char)temp ];
if( pPacket )
{
diff --git a/source/cClientHandle.h b/source/cClientHandle.h
index 6f3e3ddc0..0011903b1 100644
--- a/source/cClientHandle.h
+++ b/source/cClientHandle.h
@@ -78,6 +78,7 @@ private:
static const unsigned short PING_TIME_MS = 1000; //minecraft sends 1 per 20 ticks (1 second or every 1000 ms)
bool m_bLoggedIn;
+ bool m_bPositionConfirmed;
bool m_bSendLoginResponse;
bool m_bKeepThreadGoing;
diff --git a/source/cEntity.cpp b/source/cEntity.cpp
index ce7117498..8a841ea87 100644
--- a/source/cEntity.cpp
+++ b/source/cEntity.cpp
@@ -148,7 +148,7 @@ void cEntity::RemoveFromChunk( cChunk* a_Chunk )
{
if( m_World )
{
- cChunk* Chunk = ( a_Chunk ? a_Chunk : m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ ) );
+ cChunk* Chunk = ( a_Chunk ? a_Chunk : (cChunk*)m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ ) );
if( Chunk )
{
cPacket_DestroyEntity DestroyEntity( this );
diff --git a/source/cPickup.cpp b/source/cPickup.cpp
index c665577f0..9e9dc2666 100644
--- a/source/cPickup.cpp
+++ b/source/cPickup.cpp
@@ -197,7 +197,7 @@ void cPickup::HandlePhysics(float a_Dt)
Direction WaterDir = World->GetWaterSimulator()->GetFlowingDirection((int) m_Pos->x - 1, (int) m_Pos->y, (int) m_Pos->z - 1);
- *m_WaterSpeed *= 0.9; //Keep old speed but lower it
+ *m_WaterSpeed *= 0.9f; //Keep old speed but lower it
switch(WaterDir)
{
@@ -256,7 +256,7 @@ void cPickup::HandlePhysics(float a_Dt)
}
}
*m_Pos = Tracer.RealHit;
- *m_Pos += *Tracer.HitNormal * 0.2;
+ *m_Pos += *Tracer.HitNormal * 0.2f;
}
else
diff --git a/source/cServer.cpp b/source/cServer.cpp
index d3e8e43a7..dc4b5b5c9 100644
--- a/source/cServer.cpp
+++ b/source/cServer.cpp
@@ -277,7 +277,7 @@ void cServer::StartListenClient()
bool cServer::Tick(float a_Dt)
{
- //LOG("Tick");
+ //LOG("1. Tick");
if( a_Dt > 100.f ) a_Dt = 100.f; // Don't go over 1/10 second
cSleep::MilliSleep( 50 ); // Don't tick too much
@@ -289,7 +289,6 @@ bool cServer::Tick(float a_Dt)
m_Millisecondsf = m_Millisecondsf - (int)m_Millisecondsf;
}
-
cRoot::Get()->TickWorlds( a_Dt ); // TODO - Maybe give all worlds their own thread?
//World->LockClientHandle(); // TODO - Lock client list
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index d10d01a0d..fc7447c1d 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -45,6 +45,8 @@
#include "packets/cPacket_NewInvalidState.h"
#include "packets/cPacket_Thunderbolt.h"
+#include "ptr_cChunk.h"
+
#include "Vector3d.h"
#include
@@ -430,12 +432,11 @@ void cWorld::Tick(float a_Dt)
int TimesSpreaded = 0;
while( !m_pState->SpreadQueue.empty() && TimesSpreaded < 50 ) // Spread a max of 50 times each tick, otherwise server will hang
{
- cChunk* Chunk = (*m_pState->SpreadQueue.begin());
+ ptr_cChunk& Chunk = *m_pState->SpreadQueue.begin();
//LOG("Spreading: %p", Chunk );
Chunk->SpreadLight( Chunk->pGetSkyLight() );
Chunk->SpreadLight( Chunk->pGetLight() );
m_pState->SpreadQueue.remove( Chunk );
- Chunk->RemoveReference();
TimesSpreaded++;
}
if( TimesSpreaded >= 50 )
@@ -494,7 +495,7 @@ void cWorld::Tick(float a_Dt)
FastSetBlock( SetBlockData.x, SetBlockData.y, SetBlockData.z, SetBlockData.BlockID, SetBlockData.BlockMeta ); // If unable to set block, it's added to FastSetBlockQueue again
}
if( FastSetBlockQueueCopy.size() != m_pState->FastSetBlockQueue.size() )
- LOG(" Before: %i, after %i" , FastSetBlockQueueCopy.size(), m_pState->FastSetBlockQueue.size() );
+ LOG(" Before: %i, after %i" , FastSetBlockQueueCopy.size(), m_pState->FastSetBlockQueue.size() );
if( m_Time - m_LastSave > 60*5 ) // Save each 5 minutes
{
@@ -712,20 +713,36 @@ cChunk* cWorld::GetChunk( int a_X, int a_Y, int a_Z )
cChunk* Chunk = GetChunkUnreliable( a_X, a_Y, a_Z );
if( Chunk ) return Chunk;
+#if 1 // Current thread chunk generation
+
+ // Found nothing, create a chunk
+ Chunk = new cChunk( a_X, a_Y, a_Z, this );
+ if(Chunk)
+ {
+ LOGWARN("Created new chunk! %i %i", a_X, a_Z);
+ LockChunks();
+ m_ChunkMap->AddChunk( Chunk );
+ UnlockChunks();
+ Chunk->Initialize();
+ return Chunk;
+ }
+ return 0;
+#else // Async thread generation
+
// Generate new chunk asynchronously
m_pState->pChunkGenerator->GenerateChunk( a_X, a_Z );
// Could not find chunk, it's being generated, so return 0
return 0;
+#endif
}
-cChunk* cWorld::GetChunkUnreliable( int a_X, int a_Y, int a_Z )
+ptr_cChunk cWorld::GetChunkUnreliable( int a_X, int a_Y, int a_Z )
{
LockChunks();
- cChunk* Chunk = m_ChunkMap->GetChunk( a_X, a_Y, a_Z );
+ ptr_cChunk Chunk( m_ChunkMap->GetChunk( a_X, a_Y, a_Z ) );
UnlockChunks();
- if( Chunk ) return Chunk;
- return 0;
+ return Chunk;
}
cChunk* cWorld::GetChunkOfBlock( int a_X, int a_Y, int a_Z )
@@ -761,18 +778,6 @@ void cWorld::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_B
return;
}
- // Could not find chunk, so it has been pushed into the generate chunks queue
- // Check if currently generating the target chunk
- m_pState->pChunkGenerator->Lock();
- Chunk = m_pState->pChunkGenerator->GetCurrentlyGenerating();
- if( Chunk && Chunk->GetPosX() == ChunkX && Chunk->GetPosZ() == ChunkZ )
- {
- Chunk->FastSetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
- m_pState->pChunkGenerator->Unlock();
- return;
- }
- m_pState->pChunkGenerator->Unlock();
-
// Unable to set block right now, try again later
m_pState->FastSetBlockQueue.push_back( sSetBlockData( a_X, a_Y, a_Z, a_BlockType, a_BlockMeta ) );
}
@@ -1052,23 +1057,20 @@ void cWorld::UnlockChunks()
m_ChunksCriticalSection->Unlock();
}
-void cWorld::ReSpreadLighting( cChunk* a_Chunk )
+void cWorld::ReSpreadLighting( const ptr_cChunk& a_Chunk )
{
LockChunks();
- m_pState->SpreadQueue.remove( a_Chunk );
+ m_pState->SpreadQueue.remove( a_Chunk );
m_pState->SpreadQueue.push_back( a_Chunk );
-#define STRINGIZE(x) #x
- a_Chunk->AddReference( __FILE__ ": " STRINGIZE(__LINE__) );
+ //#define STRINGIZE(x) #x
+ //a_Chunk->AddReference( __FILE__ ": " STRINGIZE(__LINE__) );
UnlockChunks();
}
-void cWorld::RemoveSpread( cChunk* a_Chunk )
+void cWorld::RemoveSpread( const ptr_cChunk& a_Chunk )
{
LockChunks();
- size_t SizeBefore = m_pState->SpreadQueue.size();
m_pState->SpreadQueue.remove( a_Chunk );
- if( SizeBefore != m_pState->SpreadQueue.size() )
- a_Chunk->RemoveReference();
UnlockChunks();
}
diff --git a/source/cWorld.h b/source/cWorld.h
index ab99c11b1..38b7ec349 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -13,6 +13,7 @@ enum ENUM_ITEM_ID;
#include
#include "cSimulatorManager.h"
+#include "ptr_cChunk.h"
class cPacket;
class cRedstone;
@@ -36,7 +37,7 @@ class cWorld //tolua_export
public:
typedef std::list< cClientHandle* > ClientList;
typedef std::list< cEntity* > EntityList;
- typedef std::list< cChunk* > ChunkList;
+ typedef std::list< ptr_cChunk > ChunkList;
typedef std::list< cPlayer* > PlayerList;
std::vector m_RSList;
@@ -56,7 +57,7 @@ public:
cChunk* GetChunk( int a_X, int a_Y, int a_Z );
cChunk* GetChunkReliable( int a_X, int a_Y, int a_Z );
- cChunk* GetChunkUnreliable( int a_X, int a_Y, int a_Z );
+ ptr_cChunk GetChunkUnreliable( int a_X, int a_Y, int a_Z );
cChunk* GetChunkOfBlock( int a_X, int a_Y, int a_Z );
char GetHeight( int a_X, int a_Z ); //tolua_export
@@ -148,14 +149,14 @@ public:
void LockChunks();
void UnlockChunks();
- void ReSpreadLighting( cChunk* a_Chunk );
- void RemoveSpread( cChunk* a_Chunk );
+ void ReSpreadLighting( const ptr_cChunk& a_Chunk );
+ void RemoveSpread( const ptr_cChunk& a_Chunk );
void InitializeSpawn();
- void CastThunderbolt ( int, int, int ); //tolua_export
+ void CastThunderbolt ( int, int, int ); //tolua_export
void SetWeather ( int ); //tolua_export
- int GetWeather() { return m_Weather; }; //tolua_export
+ int GetWeather() { return m_Weather; }; //tolua_export
cWorldGenerator* GetWorldGenerator() { return m_WorldGenerator; }
private:
diff --git a/source/ptr_cChunk.h b/source/ptr_cChunk.h
new file mode 100644
index 000000000..c3556839c
--- /dev/null
+++ b/source/ptr_cChunk.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "cChunk.h"
+
+class ptr_cChunk
+{
+public:
+ ptr_cChunk( cChunk* a_Ptr )
+ : m_Ptr( a_Ptr )
+ {
+ if( m_Ptr ) m_Ptr->AddReference();
+ }
+
+ ptr_cChunk( const ptr_cChunk& a_Clone )
+ : m_Ptr( a_Clone.m_Ptr )
+ {
+ if( m_Ptr ) m_Ptr->AddReference();
+ }
+
+ ~ptr_cChunk()
+ {
+ if( m_Ptr ) m_Ptr->RemoveReference();
+ }
+
+ cChunk* operator-> ()
+ {
+ return m_Ptr;
+ }
+
+ cChunk& operator* () { return *m_Ptr; }
+ bool operator!() { return !m_Ptr; }
+ bool operator==( const ptr_cChunk& a_Other ) { return m_Ptr == a_Other.m_Ptr; }
+ operator bool() { return m_Ptr != 0; }
+ operator cChunk*() { return m_Ptr; }
+private:
+ cChunk* m_Ptr;
+};
\ No newline at end of file