summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/Bindings.cpp67
-rw-r--r--source/Bindings.h2
-rw-r--r--source/cChunk.cpp76
-rw-r--r--source/cChunk.h5
-rw-r--r--source/cChunkMap.cpp12
-rw-r--r--source/cChunkMap.h2
-rw-r--r--source/cClientHandle.cpp16
-rw-r--r--source/cServer.cpp2
-rw-r--r--source/cWorld.cpp16
-rw-r--r--source/cWorld.h3
10 files changed, 187 insertions, 14 deletions
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index 0256e02c4..83a9e1518 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 01/01/12 05:42:24.
+** Generated automatically by tolua++-1.0.92 on 01/01/12 17:14:14.
*/
#ifndef __cplusplus
@@ -8907,6 +8907,69 @@ static int tolua_AllToLua_cWorld_GetName00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: SaveAllChunks of class cWorld */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SaveAllChunks00
+static int tolua_AllToLua_cWorld_SaveAllChunks00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SaveAllChunks'", NULL);
+#endif
+ {
+ self->SaveAllChunks();
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SaveAllChunks'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetNumChunks of class cWorld */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetNumChunks00
+static int tolua_AllToLua_cWorld_GetNumChunks00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetNumChunks'", NULL);
+#endif
+ {
+ int tolua_ret = (int) self->GetNumChunks();
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetNumChunks'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: CastThunderbolt of class cWorld */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_CastThunderbolt00
static int tolua_AllToLua_cWorld_CastThunderbolt00(lua_State* tolua_S)
@@ -16108,6 +16171,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GrowTree",tolua_AllToLua_cWorld_GrowTree00);
tolua_function(tolua_S,"GetWorldSeed",tolua_AllToLua_cWorld_GetWorldSeed00);
tolua_function(tolua_S,"GetName",tolua_AllToLua_cWorld_GetName00);
+ tolua_function(tolua_S,"SaveAllChunks",tolua_AllToLua_cWorld_SaveAllChunks00);
+ tolua_function(tolua_S,"GetNumChunks",tolua_AllToLua_cWorld_GetNumChunks00);
tolua_function(tolua_S,"CastThunderbolt",tolua_AllToLua_cWorld_CastThunderbolt00);
tolua_function(tolua_S,"SetWeather",tolua_AllToLua_cWorld_SetWeather00);
tolua_function(tolua_S,"GetWeather",tolua_AllToLua_cWorld_GetWeather00);
diff --git a/source/Bindings.h b/source/Bindings.h
index 5b0973d35..b0ca12919 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 01/01/12 05:42:24.
+** Generated automatically by tolua++-1.0.92 on 01/01/12 17:14:15.
*/
/* Exported function */
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index fae2c2507..47e92555f 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -52,12 +52,18 @@
extern bool g_bWaterPhysics;
+typedef std::map< int, std::string > ReferenceMap;
typedef std::list< cFurnaceEntity* > FurnaceEntityList;
typedef std::list< cClientHandle* > ClientHandleList;
typedef std::list< cBlockEntity* > BlockEntityList;
typedef std::list< cEntity* > EntityList;
struct cChunk::sChunkState
{
+ sChunkState()
+ : TotalReferencesEver( 0 )
+ , MinusReferences( 0 )
+ {}
+
FurnaceEntityList TickBlockEntities;
std::map< unsigned int, int > ToTickBlocks; // Protected by BlockListCriticalSection
std::vector< unsigned int > PendingSendBlocks; // Protected by BlockListCriticalSection
@@ -67,6 +73,12 @@ struct cChunk::sChunkState
EntityList Entities;
cCriticalSection BlockListCriticalSection;
+
+ // Reference counting
+ cCriticalSection ReferenceCriticalSection;
+ 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
};
cChunk::~cChunk()
@@ -77,6 +89,13 @@ cChunk::~cChunk()
LOGWARN("WARNING: Deleting cChunk while it contains %i clients!", m_pState->LoadedByClient.size() );
}
+ m_pState->ReferenceCriticalSection.Lock();
+ if( GetReferenceCount() > 0 )
+ {
+ LOGWARN("WARNING: Deleting cChunk while it still has %i references!", GetReferenceCount() );
+ }
+ m_pState->ReferenceCriticalSection.Unlock();
+
m_pState->BlockListCriticalSection.Lock();
for( std::list<cBlockEntity*>::iterator itr = m_pState->BlockEntities.begin(); itr != m_pState->BlockEntities.end(); ++itr)
{
@@ -1158,6 +1177,63 @@ 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 */ )
+{
+ 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->ReferenceCriticalSection.Unlock();
+ return ID;
+}
+
+void cChunk::RemoveReference( int a_ID )
+{
+ m_pState->ReferenceCriticalSection.Lock();
+
+ if( a_ID > -1 ) // Remove reference with an ID
+ {
+ 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 );
+ }
+ }
+ 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;
+ m_pState->ReferenceCriticalSection.Lock();
+ return Refs;
+}
#if !C_CHUNK_USE_INLINE
# include "cChunk.inc"
diff --git a/source/cChunk.h b/source/cChunk.h
index fcf258bab..8555e01cf 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -100,6 +100,11 @@ public:
static const int c_NumBlocks = 16*128*16;
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 );
+ int GetReferenceCount();
private:
struct sChunkState;
sChunkState* m_pState;
diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp
index 90b3258e7..d05fd4a43 100644
--- a/source/cChunkMap.cpp
+++ b/source/cChunkMap.cpp
@@ -462,7 +462,7 @@ void cChunkMap::UnloadUnusedChunks()
for( int i = 0; i < LAYER_SIZE*LAYER_SIZE; ++i )
{
cChunk* Chunk = Layer.m_Chunks[i].m_LiveChunk;
- if( Chunk && Chunk->GetClients().size() == 0 )
+ if( Chunk && Chunk->GetClients().size() == 0 && Chunk->GetReferenceCount() <= 0 )
{
Chunk->SaveToDisk();
World->RemoveSpread( Chunk );
@@ -716,3 +716,13 @@ cChunkMap::cChunkLayer* cChunkMap::LoadLayer(int a_LayerX, int a_LayerZ )
}
return 0;
}
+
+int cChunkMap::GetNumChunks()
+{
+ int NumChunks = 0;
+ for( int i = 0; i < m_NumLayers; ++i )
+ {
+ NumChunks += m_Layers[i].m_NumChunksLoaded;
+ }
+ return NumChunks;
+} \ No newline at end of file
diff --git a/source/cChunkMap.h b/source/cChunkMap.h
index c728514e1..b2292870f 100644
--- a/source/cChunkMap.h
+++ b/source/cChunkMap.h
@@ -22,6 +22,8 @@ public:
void SaveAllChunks();
cWorld* GetWorld() { return m_World; }
+
+ int GetNumChunks();
private:
class cChunkData
{
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index 5daa53138..10364243e 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -127,7 +127,7 @@ cClientHandle::cClientHandle(const cSocket & a_Socket)
, m_pState( new sClientHandleState )
, m_Ping(1000)
{
- LOG("cClientHandle::cClientHandle");
+ LOG("cClientHandle::cClientHandle");
cTimer t1;
m_LastPingTime = t1.GetNowTime();
@@ -239,9 +239,9 @@ cClientHandle::~cClientHandle()
if(m_Player)
{
m_Player->SetClientHandle( 0 );
- m_Player->Destroy();
- m_Player = 0;
- }
+ m_Player->Destroy();
+ m_Player = 0;
+ }
for(int i = 0; i < 256; i++)
{
if( m_pState->PacketMap[i] )
@@ -990,7 +990,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
LOG("Dir: %i", PacketData->m_Direction);
if( PacketData->m_Direction == 1 )
{
- LOG("Player Rotation: %f", m_Player->GetRotation() );
+ LOG("Player Rotation: %f", m_Player->GetRotation() );
MetaData = cSign::RotationToMetaData( m_Player->GetRotation() );
LOG("Sign rotation %i", MetaData);
PacketData->m_ItemType = E_BLOCK_SIGN_POST;
@@ -1215,7 +1215,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
break;
case E_DISCONNECT:
{
- LOG("Received d/c packet from %s", GetUsername() );
+ LOG("Received d/c packet from %s", GetUsername() );
cPacket_Disconnect* PacketData = reinterpret_cast<cPacket_Disconnect*>(a_Packet);
if( !cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_DISCONNECT, 2, PacketData->m_Reason.c_str(), m_Player ) )
{
@@ -1237,7 +1237,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
}
break;
default:
- break;
+ break;
}
}
}
@@ -1362,7 +1362,7 @@ void cClientHandle::Send( const cPacket & a_Packet, ENUM_PRIORITY a_Priority /*
}
}
break;
- default:
+ default:
break;
}
if( bBreak )
diff --git a/source/cServer.cpp b/source/cServer.cpp
index 81444f8e1..d3e8e43a7 100644
--- a/source/cServer.cpp
+++ b/source/cServer.cpp
@@ -470,7 +470,7 @@ void cServer::ServerCommand( const char* a_Cmd )
}
if( split[0].compare( "numchunks" ) == 0 )
{
- //printf("Num loaded chunks: %i\n", cRoot::Get()->GetWorld()->GetChunks().size() );
+ printf("Num loaded chunks: %i\n", cRoot::Get()->GetWorld()->GetNumChunks() );
return;
}
if(split[0].compare("monsters") == 0 ){
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index 0b1ee7010..d10d01a0d 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -434,7 +434,8 @@ void cWorld::Tick(float a_Dt)
//LOG("Spreading: %p", Chunk );
Chunk->SpreadLight( Chunk->pGetSkyLight() );
Chunk->SpreadLight( Chunk->pGetLight() );
- m_pState->SpreadQueue.remove( &*Chunk );
+ m_pState->SpreadQueue.remove( Chunk );
+ Chunk->RemoveReference();
TimesSpreaded++;
}
if( TimesSpreaded >= 50 )
@@ -676,6 +677,7 @@ void cWorld::UnloadUnusedChunks()
m_LastUnload = m_Time;
LockChunks();
+ LOGINFO("Unloading unused chunks");
m_ChunkMap->UnloadUnusedChunks();
UnlockChunks();
}
@@ -1055,13 +1057,18 @@ void cWorld::ReSpreadLighting( cChunk* a_Chunk )
LockChunks();
m_pState->SpreadQueue.remove( a_Chunk );
m_pState->SpreadQueue.push_back( a_Chunk );
+#define STRINGIZE(x) #x
+ a_Chunk->AddReference( __FILE__ ": " STRINGIZE(__LINE__) );
UnlockChunks();
}
void cWorld::RemoveSpread( 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();
}
@@ -1102,3 +1109,10 @@ const char* cWorld::GetName()
{
return m_pState->WorldName.c_str();
}
+int cWorld::GetNumChunks()
+{
+ LockChunks();
+ int NumChunks = m_ChunkMap->GetNumChunks();
+ UnlockChunks();
+ return NumChunks;
+} \ No newline at end of file
diff --git a/source/cWorld.h b/source/cWorld.h
index 47c60fb87..ab99c11b1 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -134,7 +134,8 @@ public:
if(a_Z < 0 && a_Z % 16 != 0) a_ChunkZ--;
}
- void SaveAllChunks();
+ void SaveAllChunks(); //tolua_export
+ int GetNumChunks(); //tolua_export
void Tick(float a_Dt);