From b902546863c4b17c6d8ff3f198713aba7a8bbadd Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 26 Feb 2012 16:15:09 +0000 Subject: New cChunkStay class for temporarily keeping chunks loaded even when then have no clients. For now unused, will be used by generator and lighting in the future. git-svn-id: http://mc-server.googlecode.com/svn/trunk@330 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cChunk.cpp | 14 +++++++- source/cChunk.h | 6 ++++ source/cChunkMap.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++ source/cChunkMap.h | 30 +++++++++++++++++ source/cWorld.cpp | 9 ++++++ source/cWorld.h | 3 ++ 6 files changed, 152 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/cChunk.cpp b/source/cChunk.cpp index 058e04b99..14f99c1d9 100644 --- a/source/cChunk.cpp +++ b/source/cChunk.cpp @@ -85,6 +85,7 @@ cChunk::cChunk(int a_X, int a_Y, int a_Z, cChunkMap * a_ChunkMap, cWorld * a_Wor , m_IsValid(false) , m_IsDirty(false) , m_IsSaving(false) + , m_StayCount(0) { // LOGINFO("### new cChunk (%i, %i) at %p, thread 0x%x ###", a_X, a_Z, this, GetCurrentThreadId()); } @@ -164,7 +165,7 @@ void cChunk::SetValid(bool a_SendToClients) bool cChunk::CanUnload(void) { - return m_LoadedByClient.empty() && !m_IsDirty; + return m_LoadedByClient.empty() && !m_IsDirty && (m_StayCount == 0); } @@ -298,6 +299,17 @@ bool cChunk::HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ) +/// Sets or resets the internal flag that prevents chunk from being unloaded +void cChunk::Stay(bool a_Stay) +{ + m_StayCount += (a_Stay ? 1 : -1); + ASSERT(m_StayCount >= 0); +} + + + + + void cChunk::Tick(float a_Dt, MTRand & a_TickRandom) { if (m_bCalculateLighting) diff --git a/source/cChunk.h b/source/cChunk.h index f0e47834d..3dc1c56fd 100644 --- a/source/cChunk.h +++ b/source/cChunk.h @@ -146,6 +146,9 @@ public: /// Returns true if there is a block entity at the coords specified bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ); + /// Sets or resets the internal flag that prevents chunk from being unloaded + void Stay(bool a_Stay = true); + void Tick(float a_Dt, MTRand & a_TickRandom); int GetPosX() { return m_PosX; } @@ -238,6 +241,9 @@ private: cClientHandleList m_UnloadQuery; cEntityList m_Entities; cBlockEntityList m_BlockEntities; + + /// Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded + int m_StayCount; bool m_bCalculateLighting; diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp index d9964c9d2..548040724 100644 --- a/source/cChunkMap.cpp +++ b/source/cChunkMap.cpp @@ -755,6 +755,21 @@ void cChunkMap::UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, c +void cChunkMap::ChunkStay(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Stay) +{ + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ); + if (Chunk == NULL) + { + return; + } + Chunk->Stay(a_Stay); +} + + + + + void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom ) { cCSLock Lock(m_CSLayers); @@ -939,3 +954,79 @@ void cChunkMap::ChunkValidated(void) + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cChunkStay: + +cChunkStay::cChunkStay(cWorld * a_World) : + m_World(a_World) +{ +} + + + + + +cChunkStay::~cChunkStay() +{ + Clear(); +} + + + + + +void cChunkStay::Clear(void) +{ + cChunkCoordsList Chunks; + { + cCSLock Lock(m_CS); + std::swap(Chunks, m_Chunks); + } + + // Un-"stay" all chunks: + for (cChunkCoordsList::const_iterator itr = Chunks.begin(); itr != Chunks.end(); ++itr) + { + m_World->ChunkStay(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ, false); + } // for itr - Chunks[] +} + + + + + +void cChunkStay::Add(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + cCSLock Lock(m_CS); + for (cChunkCoordsList::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr) + { + if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ)) + { + // Already "stayed" + return; + } + } // for itr - Chunks[] + m_World->ChunkStay(a_ChunkX, a_ChunkY, a_ChunkZ); +} + + + + + +void cChunkStay::Remove(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + cCSLock Lock(m_CS); + for (cChunkCoordsList::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr) + { + if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ)) + { + // Found, un-"stay" + m_World->ChunkStay(a_ChunkX, a_ChunkY, a_ChunkZ, false); + return; + } + } // for itr - Chunks[] +} + + + + diff --git a/source/cChunkMap.h b/source/cChunkMap.h index 7de26ee28..21e52c5a8 100644 --- a/source/cChunkMap.h +++ b/source/cChunkMap.h @@ -15,6 +15,7 @@ class cWorld; class cEntity; class cItem; class MTRand; +class cChunkStay; @@ -83,6 +84,9 @@ public: void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ); void UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); + + /// Marks (a_Stay == true) or unmarks (a_Stay == false) a chunk as non-unloadable; to be used only by cChunkStay! + void ChunkStay(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Stay = true); void Tick( float a_Dt, MTRand & a_TickRand ); @@ -173,3 +177,29 @@ private: + +/** Makes chunks stay loaded until this object is cleared or destroyed +Works by setting internal flags in the cChunk that it should not be unloaded +*/ +class cChunkStay +{ +public: + cChunkStay(cWorld * a_World); + ~cChunkStay(); + + void Clear(void); + + void Add(int a_ChunkX, int a_ChunkY, int a_ChunkZ); + void Remove(int a_ChunkX, int a_ChunkY, int a_ChunkZ); + +protected: + + cWorld * m_World; + + cCriticalSection m_CS; + cChunkCoordsList m_Chunks; +} ; + + + + diff --git a/source/cWorld.cpp b/source/cWorld.cpp index f8cef7cbb..ff2078f08 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -1297,6 +1297,15 @@ void cWorld::UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, cons +void cWorld::ChunkStay(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Stay) +{ + m_ChunkMap->ChunkStay(a_ChunkX, a_ChunkY, a_ChunkZ, a_Stay); +} + + + + + void cWorld::SaveAllChunks() { LOG("Saving all chunks..."); diff --git a/source/cWorld.h b/source/cWorld.h index 7551740ab..3be462d99 100644 --- a/source/cWorld.h +++ b/source/cWorld.h @@ -129,6 +129,9 @@ public: void UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); + /// Marks (a_Stay == true) or unmarks (a_Stay == false) a chunk as non-unloadable; to be used only by cChunkStay! + void ChunkStay(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Stay = true); + // TODO: Export to Lua bool DoWithEntity( int a_UniqueID, cEntityCallback & a_Callback ); -- cgit v1.2.3