Fixed the numchunks console command.
Added some form of reference counting to cChunk to make sure it's not referenced when deleting it. Right now it's only needed due to the generation of chunks in a separate thread and adding it to the spread light list in cWorld git-svn-id: http://mc-server.googlecode.com/svn/trunk@161 0a769ca7-a7f5-676a-18bf-c427514a06d6master
parent
d7068b35a8
commit
01398f8424
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -22,6 +22,8 @@ public:
|
|||
void SaveAllChunks();
|
||||
|
||||
cWorld* GetWorld() { return m_World; }
|
||||
|
||||
int GetNumChunks();
|
||||
private:
|
||||
class cChunkData
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 ){
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue