From 1f88db187bbc1bacc29a2f263c73ff383aa06e91 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 26 Feb 2012 16:46:23 +0000 Subject: [PATCH] Implemented chunk loading without generating on load-failure git-svn-id: http://mc-server.googlecode.com/svn/trunk@331 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/WorldStorage.cpp | 44 +++++++++++++++++++++++++++++++---------- source/WorldStorage.h | 18 ++++++++++++++--- source/cChunkMap.cpp | 16 ++++++++++++--- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/source/WorldStorage.cpp b/source/WorldStorage.cpp index 58c6527ca..2d8d5bbc7 100644 --- a/source/WorldStorage.cpp +++ b/source/WorldStorage.cpp @@ -196,12 +196,20 @@ int cWorldStorage::GetSaveQueueLength(void) -void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) { // Queues the chunk for loading; if not loaded, the chunk will be generated cCSLock Lock(m_CSQueues); - m_LoadQueue.remove (cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); // Don't add twice - m_LoadQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); + + // Check if already in the queue: + for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr) + { + if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ) && (itr->m_Generate == a_Generate)) + { + return; + } + } + m_LoadQueue.push_back(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate)); m_Event.Set(); } @@ -221,11 +229,19 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) -void cWorldStorage::UnqueueLoad(const cChunkCoords & a_Chunk) +void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ) { cCSLock Lock(m_CSQueues); - m_LoadQueue.remove(a_Chunk); - m_evtRemoved.Set(); + for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr) + { + if ((itr->m_ChunkX != a_ChunkX) || (itr->m_ChunkY != a_ChunkY) || (itr->m_ChunkZ != a_ChunkZ)) + { + continue; + } + m_LoadQueue.erase(itr); + m_evtRemoved.Set(); + return; + } // for itr - m_LoadQueue[] } @@ -306,7 +322,7 @@ void cWorldStorage::Execute(void) bool cWorldStorage::LoadOneChunk(void) { - cChunkCoords ToLoad(0, 0, 0); + sChunkLoad ToLoad(0, 0, 0, false); bool HasMore; bool ShouldLoad = false; { @@ -319,10 +335,18 @@ bool cWorldStorage::LoadOneChunk(void) } HasMore = (m_LoadQueue.size() > 0); } - if (ShouldLoad && !LoadChunk(ToLoad)) + if (ShouldLoad && !LoadChunk(cChunkCoords(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ))) { - // The chunk couldn't be loaded, generate it: - m_World->GetGenerator().GenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); + if (ToLoad.m_Generate) + { + // The chunk couldn't be loaded, generate it: + m_World->GetGenerator().GenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); + } + else + { + // TODO: Notify the world that the load has failed: + // m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); + } } return HasMore; } diff --git a/source/WorldStorage.h b/source/WorldStorage.h index 1ea39cf66..9c3a38771 100644 --- a/source/WorldStorage.h +++ b/source/WorldStorage.h @@ -97,10 +97,10 @@ public: cWorldStorage(void); ~cWorldStorage(); - void QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Queues the chunk for loading; if not loaded, the chunk will be generated + void QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate); // Queues the chunk for loading; if not loaded, the chunk will be generated if a_Generate is true void QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ); - void UnqueueLoad(const cChunkCoords & a_Chunk); + void UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ); void UnqueueSave(const cChunkCoords & a_Chunk); bool Start(cWorld * a_World, const AString & a_StorageSchemaName); // Hide the cIsThread's Start() method, we need to provide args @@ -112,12 +112,24 @@ public: protected: + struct sChunkLoad + { + int m_ChunkX; + int m_ChunkY; + int m_ChunkZ; + bool m_Generate; // If true, the chunk will be generated if it cannot be loaded + + sChunkLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkY(a_ChunkY), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {} + } ; + + typedef std::list sChunkLoadQueue; + cWorld * m_World; AString m_StorageSchemaName; // Both queues are locked by the same CS cCriticalSection m_CSQueues; - cChunkCoordsList m_LoadQueue; + sChunkLoadQueue m_LoadQueue; cChunkCoordsList m_SaveQueue; cEvent m_Event; // Set when there's any addition to the queues diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp index 548040724..52e124107 100644 --- a/source/cChunkMap.cpp +++ b/source/cChunkMap.cpp @@ -115,9 +115,13 @@ cChunkPtr cChunkMap::GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) } cChunkPtr Chunk = Layer->GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ); + if (Chunk == NULL) + { + return NULL; + } if (!(Chunk->IsValid())) { - m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ); + m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ, true); } return Chunk; } @@ -137,8 +141,14 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) } cChunkPtr Chunk = Layer->GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ); - - // TODO: Load, but do not generate, if not valid + if (Chunk == NULL) + { + return NULL; + } + if (!(Chunk->IsValid())) + { + m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ, false); + } return Chunk; }