diff options
author | madmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-02-26 17:15:09 +0100 |
---|---|---|
committer | madmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-02-26 17:15:09 +0100 |
commit | b902546863c4b17c6d8ff3f198713aba7a8bbadd (patch) | |
tree | 35e67849dc70672b8ccfaf0aeb7e8d8293d639f4 | |
parent | Attempt at fixing crashes with disconnecting players (diff) | |
download | cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.tar cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.tar.gz cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.tar.bz2 cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.tar.lz cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.tar.xz cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.tar.zst cuberite-b902546863c4b17c6d8ff3f198713aba7a8bbadd.zip |
-rw-r--r-- | source/cChunk.cpp | 14 | ||||
-rw-r--r-- | source/cChunk.h | 6 | ||||
-rw-r--r-- | source/cChunkMap.cpp | 91 | ||||
-rw-r--r-- | source/cChunkMap.h | 30 | ||||
-rw-r--r-- | source/cWorld.cpp | 9 | ||||
-rw-r--r-- | source/cWorld.h | 3 |
6 files changed, 152 insertions, 1 deletions
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 );
|