summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft <github@xoft.cz>2014-02-08 21:55:21 +0100
committermadmaxoft <github@xoft.cz>2014-02-08 21:55:21 +0100
commitea71bfa9b645cda80b7d4364c675ebaee8db8353 (patch)
tree8db9fc2cd467e32bebd2aae4aaac2208fee60c2f
parentMerge pull request #653 from mc-server/RedstoneSimulator (diff)
downloadcuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.tar
cuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.tar.gz
cuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.tar.bz2
cuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.tar.lz
cuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.tar.xz
cuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.tar.zst
cuberite-ea71bfa9b645cda80b7d4364c675ebaee8db8353.zip
-rw-r--r--src/Chunk.cpp1
-rw-r--r--src/Chunk.h110
-rw-r--r--src/ChunkDef.h1
-rw-r--r--src/ChunkMap.cpp185
-rw-r--r--src/ChunkMap.h199
-rw-r--r--src/ChunkStay.cpp136
-rw-r--r--src/ChunkStay.h92
-rw-r--r--src/LightingThread.cpp151
-rw-r--r--src/LightingThread.h76
-rw-r--r--src/World.cpp12
-rw-r--r--src/World.h3
11 files changed, 560 insertions, 406 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index b48bfe65e..3028d24d0 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -422,7 +422,6 @@ 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);
diff --git a/src/Chunk.h b/src/Chunk.h
index 3dc83b157..93eba217e 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -85,10 +85,10 @@ public:
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
void MarkLoadFailed(void); // Marks the chunk as failed to load. Ignored is the chunk is already valid
- /// Gets all chunk data, calls the a_Callback's methods for each data type
+ /** Gets all chunk data, calls the a_Callback's methods for each data type */
void GetAllData(cChunkDataCallback & a_Callback);
- /// Sets all chunk data
+ /** Sets all chunk data */
void SetAllData(
const BLOCKTYPE * a_BlockTypes,
const NIBBLETYPE * a_BlockMeta,
@@ -104,27 +104,29 @@ public:
const cChunkDef::BlockNibbles & a_SkyLight
);
- /// Copies m_BlockData into a_BlockTypes, only the block types
+ /** Copies m_BlockData into a_BlockTypes, only the block types */
void GetBlockTypes(BLOCKTYPE * a_BlockTypes);
- /// Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk!
+ /** Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk! */
void WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
- /// Returns true if there is a block entity at the coords specified
+ /** 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
+ /** Sets or resets the internal flag that prevents chunk from being unloaded.
+ The flag is cumulative - it can be set multiple times and then needs to be un-set that many times
+ before the chunk is unloadable again. */
void Stay(bool a_Stay = true);
- /// Recence all mobs proximities to players in order to know what to do with them
+ /** Recence all mobs proximities to players in order to know what to do with them */
void CollectMobCensus(cMobCensus& toFill);
- /// Try to Spawn Monsters inside chunk
+ /** Try to Spawn Monsters inside chunk */
void SpawnMobs(cMobSpawner& a_MobSpawner);
void Tick(float a_Dt);
- /// Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks
+ /** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
int GetPosX(void) const { return m_PosX; }
@@ -137,13 +139,13 @@ public:
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }
- /// Queues a block change till the specified world tick
+ /** Queues a block change till the specified world tick */
void QueueSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
- /// Queues block for ticking (m_ToTickQueue)
+ /** Queues block for ticking (m_ToTickQueue) */
void QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
- /// Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk
+ /** Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk */
void QueueTickBlockNeighbors(int a_RelX, int a_RelY, int a_RelZ);
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
@@ -175,14 +177,14 @@ public:
void CollectPickupsByPlayer(cPlayer * a_Player);
- /// Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk
+ /** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
int GetHeight( int a_X, int a_Z );
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
- /// Adds a client to the chunk; returns true if added, false if already there
+ /** Adds a client to the chunk; returns true if added, false if already there */
bool AddClient (cClientHandle* a_Client );
void RemoveClient (cClientHandle* a_Client );
@@ -193,55 +195,55 @@ public:
void RemoveEntity(cEntity * a_Entity);
bool HasEntity(int a_EntityID);
- /// Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
+ /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
- /// Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */
bool ForEachBlockEntity(cBlockEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true
+ /** Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true */
bool ForEachChest(cChestCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each dispenser; returns true if all dispensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dispenser; returns true if all dispensers processed, false if the callback aborted by returning true */
bool ForEachDispenser(cDispenserCallback & a_Callback);
- /// Calls the callback for each dropper; returns true if all droppers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropper; returns true if all droppers processed, false if the callback aborted by returning true */
bool ForEachDropper(cDropperCallback & a_Callback);
- /// Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true */
bool ForEachDropSpenser(cDropSpenserCallback & a_Callback);
- /// Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true
+ /** Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true */
bool ForEachFurnace(cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found
+ /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found
+ /** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback);
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback);
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback);
- /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
+ /** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ /** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback);
- /// Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found
+ /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback);
- /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
+ /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
@@ -292,7 +294,7 @@ public:
m_IsSaving = false;
}
- /// Sets the blockticking to start at the specified block. Only one blocktick may be set, second call overwrites the first call
+ /** Sets the blockticking to start at the specified block. Only one blocktick may be set, second call overwrites the first call */
inline void SetNextBlockTick(int a_RelX, int a_RelY, int a_RelZ)
{
m_BlockTickX = a_RelX;
@@ -310,34 +312,34 @@ public:
inline NIBBLETYPE GetBlockLight(int a_Idx) const {return cChunkDef::GetNibble(m_BlockLight, a_Idx); }
inline NIBBLETYPE GetSkyLight (int a_Idx) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_Idx); }
- /// Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
- /// Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType) const;
- /// Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockMeta) const;
- /// Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight) const;
- /// Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_SkyLight) const;
- /// Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelGetBlockLights(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const;
- /// Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success
+ /** Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
bool UnboundedRelFastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Same as QueueTickBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s in such a case), ignores unsuccessful attempts
+ /** Same as QueueTickBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s in such a case), ignores unsuccessful attempts */
void UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
- /// Light alterations based on time
+ /** Light alterations based on time */
NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const;
@@ -389,7 +391,7 @@ private:
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
+ /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
int m_StayCount;
int m_PosX, m_PosY, m_PosZ;
@@ -427,40 +429,40 @@ private:
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
void AddBlockEntity (cBlockEntity * a_BlockEntity);
- /// Creates a block entity for each block that needs a block entity and doesn't have one in the list
+ /** Creates a block entity for each block that needs a block entity and doesn't have one in the list */
void CreateBlockEntities(void);
- /// Wakes up each simulator for its specific blocks; through all the blocks in the chunk
+ /** Wakes up each simulator for its specific blocks; through all the blocks in the chunk */
void WakeUpSimulators(void);
// Makes a copy of the list
cClientHandleList GetAllClients(void) const {return m_LoadedByClient; }
- /// Sends m_PendingSendBlocks to all clients
+ /** Sends m_PendingSendBlocks to all clients */
void BroadcastPendingBlockChanges(void);
- /// Checks the block scheduled for checking in m_ToTickBlocks[]
+ /** Checks the block scheduled for checking in m_ToTickBlocks[] */
void CheckBlocks();
- /// Ticks several random blocks in the chunk
+ /** Ticks several random blocks in the chunk */
void TickBlocks(void);
- /// Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes
+ /** Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes */
void ApplyWeatherToTop(void);
- /// Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking)
+ /** Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
void GrowSugarcane (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
- /// Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking)
+ /** Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
void GrowCactus (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
- /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem)
+ /** Grows a melon or a pumpkin next to the block specified (assumed to be the stem) */
void GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random);
- /// Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients
+ /** Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients */
void MoveEntityToNewChunk(cEntity * a_Entity);
- /// Processes all blocks that have been scheduled for replacement by the QueueSetBlock() function
+ /** Processes all blocks that have been scheduled for replacement by the QueueSetBlock() function */
void ProcessQueuedSetBlocks(void);
};
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index 1c4aa6aca..f48dc4fd5 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -481,6 +481,7 @@ public:
} ;
typedef std::list<cChunkCoords> cChunkCoordsList;
+typedef std::vector<cChunkCoords> cChunkCoordsVector;
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 757396a20..a9f6bf00b 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -134,7 +134,7 @@ cChunkMap::cChunkLayer * cChunkMap::GetLayerForChunk(int a_ChunkX, int a_ChunkZ)
-cChunkPtr cChunkMap::GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
+cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
// No need to lock m_CSLayers, since it's already locked by the operation that called us
ASSERT(m_CSLayers.IsLockedByCurrentThread());
@@ -897,17 +897,25 @@ void cChunkMap::SetChunkData(
bool a_MarkDirty
)
{
- cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
- if (Chunk == NULL)
- {
- return;
- }
- Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
-
- if (a_MarkDirty)
{
- Chunk->MarkDirty();
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ if (Chunk == NULL)
+ {
+ return;
+ }
+ Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
+
+ if (a_MarkDirty)
+ {
+ Chunk->MarkDirty();
+ }
+
+ // Notify relevant ChunkStays:
+ for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
+ {
+ (*itr)->ChunkAvailable(a_ChunkX, a_ChunkZ);
+ } // for itr - m_ChunkStays[]
}
// Notify plugins of the chunk becoming available
@@ -2206,24 +2214,6 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt
-void cChunkMap::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
-{
- cCSLock Lock(m_CSLayers);
- for (cChunkCoordsList::const_iterator itr = a_Chunks.begin(); itr != a_Chunks.end(); ++itr)
- {
- cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
- if (Chunk == NULL)
- {
- continue;
- }
- Chunk->Stay(a_Stay);
- }
-}
-
-
-
-
-
void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
@@ -2810,12 +2800,16 @@ void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
-void cChunkMap::FastSetBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+void cChunkMap::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CSFastSetBlock);
- m_FastSetBlockQueue.push_back(sSetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta));
+ m_FastSetBlockQueue.push_back(sSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta));
}
+
+
+
+
void cChunkMap::FastSetQueuedBlocks()
{
// Asynchronously set blocks:
@@ -2834,110 +2828,75 @@ void cChunkMap::FastSetQueuedBlocks()
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cChunkStay:
-
-cChunkStay::cChunkStay(cWorld * a_World) :
- m_World(a_World),
- m_IsEnabled(false)
-{
-}
-
-
-
-
-
-cChunkStay::~cChunkStay()
-{
- Clear();
-}
-
-
-
-
-
-void cChunkStay::Clear(void)
-{
- if (m_IsEnabled)
- {
- Disable();
- }
- m_Chunks.clear();
-}
-
-
-void cChunkStay::Add(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkMap::AddChunkStay(cChunkStay & a_ChunkStay)
{
- ASSERT(!m_IsEnabled);
-
- for (cChunkCoordsList::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ cCSLock Lock(m_CSLayers);
+
+ // Add it to the list:
+ ASSERT(std::find(m_ChunkStays.begin(), m_ChunkStays.end(), &a_ChunkStay) == m_ChunkStays.end()); // Has not yet been added
+ m_ChunkStays.push_back(&a_ChunkStay);
+
+ // Schedule all chunks to be loaded / generated, and mark each as locked:
+ const cChunkCoordsVector & WantedChunks = a_ChunkStay.GetChunks();
+ for (cChunkCoordsVector::const_iterator itr = WantedChunks.begin(); itr != WantedChunks.end(); ++itr)
{
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ))
+ cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ if (Chunk == NULL)
{
- // Already present
- return;
+ continue;
}
- } // for itr - Chunks[]
- m_Chunks.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ Chunk->Stay(true);
+ if (Chunk->IsValid())
+ {
+ a_ChunkStay.ChunkAvailable(itr->m_ChunkX, itr->m_ChunkZ);
+ }
+ } // for itr - WantedChunks[]
}
-void cChunkStay::Remove(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+/** Removes the specified cChunkStay descendant from the internal list of ChunkStays. */
+void cChunkMap::DelChunkStay(cChunkStay & a_ChunkStay)
{
- ASSERT(!m_IsEnabled);
-
- for (cChunkCoordsList::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ cCSLock Lock(m_CSLayers);
+
+ // Remove from the list of active chunkstays:
+ bool HasFound = false;
+ for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
{
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ))
+ if (*itr == &a_ChunkStay)
{
- // Found, un-"stay"
- m_Chunks.erase(itr);
- return;
+ m_ChunkStays.erase(itr);
+ HasFound = true;
+ break;
}
- } // for itr - m_Chunks[]
-}
-
-
-
-
-
-void cChunkStay::Enable(void)
-{
- ASSERT(!m_IsEnabled);
+ } // for itr - m_ChunkStays[]
- m_World->ChunksStay(*this, true);
- m_IsEnabled = true;
-}
-
-
-
-
-
-void cChunkStay::Load(void)
-{
- for (cChunkCoordsList::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ if (!HasFound)
+ {
+ ASSERT(!"Removing a cChunkStay that hasn't been added!");
+ return;
+ }
+
+ // Unmark all contained chunks:
+ const cChunkCoordsVector & Chunks = a_ChunkStay.GetChunks();
+ for (cChunkCoordsVector::const_iterator itr = Chunks.begin(), end = Chunks.end(); itr != end; ++itr)
{
- m_World->TouchChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
- } // for itr - m_Chunks[]
+ cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ if (Chunk == NULL)
+ {
+ continue;
+ }
+ Chunk->Stay(false);
+ } // for itr - Chunks[]
}
-void cChunkStay::Disable(void)
-{
- ASSERT(m_IsEnabled);
-
- m_World->ChunksStay(*this, false);
- m_IsEnabled = false;
-}
-
-
-
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 62c74d81c..d713d0cf5 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -85,19 +85,19 @@ public:
void BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
- /// Sends the block entity, if it is at the coords specified, to a_Client
+ /** Sends the block entity, if it is at the coords specified, to a_Client */
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
- /// a_Player rclked block entity at the coords specified, handle it
+ /** a_Player rclked block entity at the coords specified, handle it */
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z);
- /// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback
+ /** Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
- /// Wakes up simulators for the specified block
+ /** Wakes up simulators for the specified block */
void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Wakes up the simulators for the specified area of blocks
+ /** Wakes up the simulators for the specified area of blocks */
void WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ);
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
@@ -130,7 +130,7 @@ public:
bool GetChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback);
- /// Copies the chunk's blocktypes into a_Blocks; returns true if successful
+ /** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
@@ -153,154 +153,151 @@ public:
bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
- /// Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType
+ /** Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType */
void ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType);
- /// Special function used for growing trees, replaces only blocks that tree may overwrite
+ /** Special function used for growing trees, replaces only blocks that tree may overwrite */
void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
EMCSBiome GetBiomeAt (int a_BlockX, int a_BlockZ);
- /// Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read.
+ /** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */
bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure);
bool DigBlock (int a_X, int a_Y, int a_Z);
void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player);
- /// Compares clients of two chunks, calls the callback accordingly
+ /** Compares clients of two chunks, calls the callback accordingly */
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
- /// Compares clients of two chunks, calls the callback accordingly
+ /** Compares clients of two chunks, calls the callback accordingly */
void CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback);
- /// Adds client to a chunk, if not already present; returns true if added, false if present
+ /** Adds client to a chunk, if not already present; returns true if added, false if present */
bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
- /// Removes the client from the chunk
+ /** Removes the client from the chunk */
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
- /// Removes the client from all chunks it is present in
+ /** Removes the client from all chunks it is present in */
void RemoveClientFromChunks(cClientHandle * a_Client);
- /// Adds the entity to its appropriate chunk, takes ownership of the entity pointer
+ /** Adds the entity to its appropriate chunk, takes ownership of the entity pointer */
void AddEntity(cEntity * a_Entity);
- /// Returns true if the entity with specified ID is present in the chunks
+ /** Returns true if the entity with specified ID is present in the chunks */
bool HasEntity(int a_EntityID);
- /// Removes the entity from its appropriate chunk
+ /** Removes the entity from its appropriate chunk */
void RemoveEntity(cEntity * a_Entity);
- /// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
- /// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates
+ /** Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates */
void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected);
- /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
+ /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true */
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true
+ /** Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true */
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Lua-accessible
- /// Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true */
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback);
- /// Calls the callback for each dropper in the specified chunk; returns true if all droppers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropper in the specified chunk; returns true if all droppers processed, false if the callback aborted by returning true */
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback & a_Callback);
- /// Calls the callback for each dropspenser in the specified chunk; returns true if all dropspensers processed, false if the callback aborted by returning true
+ /** Calls the callback for each dropspenser in the specified chunk; returns true if all dropspensers processed, false if the callback aborted by returning true */
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback & a_Callback);
- /// Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true
+ /** Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true */
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found
+ /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found
+ /** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
- /// Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the dropper at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dropper at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the dropspenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found
+ /** Calls the callback for the dropspenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
+ /** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ /** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Lua-accessible
- /// Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found
+ /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible
- /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
+ /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
- /// Touches the chunk, causing it to be loaded or generated
+ /** Touches the chunk, causing it to be loaded or generated */
void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before)
+ /** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
bool LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid()
+ /** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
void LoadChunks(const cChunkCoordsList & a_Chunks);
- /// Marks the chunk as failed-to-load
+ /** Marks the chunk as failed-to-load */
void ChunkLoadFailed(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Sets the sign text. Returns true if sign text changed.
+ /** Sets the sign text. Returns true if sign text changed. */
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, 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) chunks as non-unloadable; to be used only by cChunkStay!
- void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true);
-
- /// Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk() )
+ /** Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk() ) */
void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ);
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ);
- /// Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully
+ /** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */
bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback);
- /// Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead.
+ /** Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead. */
bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
- /// Returns the number of valid chunks and the number of dirty chunks
+ /** Returns the number of valid chunks and the number of dirty chunks */
void GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty);
- /// Grows a melon or a pumpkin next to the block specified (assumed to be the stem)
+ /** Grows a melon or a pumpkin next to the block specified (assumed to be the stem) */
void GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, MTRand & a_Rand);
- /// Grows a sugarcane present at the block specified by the amount of blocks specified, up to the max height specified in the config
+ /** Grows a sugarcane present at the block specified by the amount of blocks specified, up to the max height specified in the config */
void GrowSugarcane(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
- /// Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config
+ /** Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config */
void GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
- /// Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call
+ /** Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call */
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Make a Mob census, of all mobs, their family, their chunk and theyr distance to closest player
+ /** Make a Mob census, of all mobs, their family, their chunk and theyr distance to closest player */
void CollectMobCensus(cMobCensus& a_ToFill);
- /// Try to Spawn Monsters inside all Chunks
+ /** Try to Spawn Monsters inside all Chunks */
void SpawnMobs(cMobSpawner& a_MobSpawner);
void Tick(float a_Dt);
- /// Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks
+ /** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
void TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
void UnloadUnusedChunks(void);
@@ -312,15 +309,20 @@ public:
void ChunkValidated(void); // Called by chunks that have become valid
- /// Queues the specified block for ticking (block update)
+ /** Queues the specified block for ticking (block update) */
void QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Returns the CS for locking the chunkmap; only cWorld::cLock may use this function!
+ /** Returns the CS for locking the chunkmap; only cWorld::cLock may use this function! */
cCriticalSection & GetCS(void) { return m_CSLayers; }
private:
- friend class cChunk; // The chunks can manipulate neighbors while in their Tick() method, using LockedGetBlock() and LockedSetBlock()
+ // The chunks can manipulate neighbors while in their Tick() method, using LockedGetBlock() and LockedSetBlock()
+ friend class cChunk;
+
+ // The chunkstay can (de-)register itself using AddChunkStay() and DelChunkStay()
+ friend class cChunkStay;
+
class cChunkLayer
{
@@ -328,10 +330,10 @@ private:
cChunkLayer(int a_LayerX, int a_LayerZ, cChunkMap * a_Parent);
~cChunkLayer();
- /// Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check
+ /** Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check */
cChunkPtr GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ );
- /// Returns the specified chunk, or NULL if not created yet
+ /** Returns the specified chunk, or NULL if not created yet */
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ);
int GetX(void) const {return m_LayerX; }
@@ -344,22 +346,22 @@ private:
void Save(void);
void UnloadUnusedChunks(void);
- /// Collect a mob census, of all mobs, their megatype, their chunk and their distance o closest player
+ /** Collect a mob census, of all mobs, their megatype, their chunk and their distance o closest player */
void CollectMobCensus(cMobCensus& a_ToFill);
- /// Try to Spawn Monsters inside all Chunks
+ /** Try to Spawn Monsters inside all Chunks */
void SpawnMobs(cMobSpawner& a_MobSpawner);
void Tick(float a_Dt);
void RemoveClient(cClientHandle * a_Client);
- /// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
+ /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
- /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
+ /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn); // Lua-accessible
- /// Returns true if there is an entity with the specified ID within this layer's chunks
+ /** Returns true if there is an entity with the specified ID within this layer's chunks */
bool HasEntity(int a_EntityID);
protected:
@@ -372,17 +374,19 @@ private:
};
typedef std::list<cChunkLayer *> cChunkLayerList;
+
+ typedef std::list<cChunkStay *> cChunkStays;
- /// Finds the cChunkLayer object responsible for the specified chunk; returns NULL if not found. Assumes m_CSLayers is locked.
+ /** Finds the cChunkLayer object responsible for the specified chunk; returns NULL if not found. Assumes m_CSLayers is locked. */
cChunkLayer * FindLayerForChunk(int a_ChunkX, int a_ChunkZ);
- /// Returns the specified cChunkLayer object; returns NULL if not found. Assumes m_CSLayers is locked.
+ /** Returns the specified cChunkLayer object; returns NULL if not found. Assumes m_CSLayers is locked. */
cChunkLayer * FindLayer(int a_LayerX, int a_LayerZ);
- /// Returns the cChunkLayer object responsible for the specified chunk; creates it if not found.
+ /** Returns the cChunkLayer object responsible for the specified chunk; creates it if not found. */
cChunkLayer * GetLayerForChunk (int a_ChunkX, int a_ChunkZ);
- /// Returns the specified cChunkLayer object; creates it if not found.
+ /** Returns the specified cChunkLayer object; creates it if not found. */
cChunkLayer * GetLayer(int a_LayerX, int a_LayerZ);
void RemoveLayer(cChunkLayer * a_Layer);
@@ -395,67 +399,42 @@ private:
cCriticalSection m_CSFastSetBlock;
sSetBlockList m_FastSetBlockQueue;
+
+ /** The cChunkStay descendants that are currently enabled in this chunkmap */
+ cChunkStays m_ChunkStays;
cChunkPtr GetChunk (int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Also queues the chunk for loading / generating if not valid
cChunkPtr GetChunkNoGen (int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Also queues the chunk for loading if not valid; doesn't generate
cChunkPtr GetChunkNoLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Doesn't load, doesn't generate
- /// Gets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Gets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
- /// Gets a block type in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Gets a block type in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType);
- /// Gets a block meta in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Gets a block meta in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE & a_BlockMeta);
- /// Sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Fast-sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load)
+ /** Fast-sets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedFastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /// Locates a chunk ptr in the chunkmap; doesn't create it when not found; assumes m_CSLayers is locked. To be called only from cChunkMap.
+ /** Locates a chunk ptr in the chunkmap; doesn't create it when not found; assumes m_CSLayers is locked. To be called only from cChunkMap. */
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ);
-};
-
-
-
-
-/** 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.
-To optimize for speed, cChunkStay has an Enabled flag, it will "stay" the chunks only when enabled and it will refuse manipulations when enabled
-The object itself is not made thread-safe, it's supposed to be used from a single thread only.
-*/
-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);
-
- void Enable(void);
- void Disable(void);
+ /** Adds a new cChunkStay descendant to the internal list of ChunkStays; loads its chunks.
+ To be used only by cChunkStay; others should use cChunkStay::Enable() instead */
+ void AddChunkStay(cChunkStay & a_ChunkStay);
- /// Queues each chunk in m_Chunks[] for loading / generating
- void Load(void);
+ /** Removes the specified cChunkStay descendant from the internal list of ChunkStays.
+ To be used only by cChunkStay; others should use cChunkStay::Disable() instead */
+ void DelChunkStay(cChunkStay & a_ChunkStay);
- // Allow cChunkStay be passed to functions expecting a const cChunkCoordsList &
- operator const cChunkCoordsList(void) const {return m_Chunks; }
-
-protected:
+};
- cWorld * m_World;
-
- bool m_IsEnabled;
-
- cChunkCoordsList m_Chunks;
-} ;
diff --git a/src/ChunkStay.cpp b/src/ChunkStay.cpp
new file mode 100644
index 000000000..a64a2a3e4
--- /dev/null
+++ b/src/ChunkStay.cpp
@@ -0,0 +1,136 @@
+
+// ChunkStay.cpp
+
+// Implements the cChunkStay class representing a base for classes that keep chunks loaded
+
+#include "Globals.h"
+#include "ChunkStay.h"
+#include "ChunkMap.h"
+
+
+
+
+
+cChunkStay::cChunkStay(void) :
+ m_ChunkMap(NULL)
+{
+}
+
+
+
+
+
+cChunkStay::~cChunkStay()
+{
+ Clear();
+}
+
+
+
+
+
+void cChunkStay::Clear(void)
+{
+ if (m_ChunkMap != NULL)
+ {
+ Disable();
+ }
+ m_Chunks.clear();
+}
+
+
+
+
+
+void cChunkStay::Add(int a_ChunkX, int a_ChunkZ)
+{
+ ASSERT(m_ChunkMap == NULL);
+
+ for (cChunkCoordsVector::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ {
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
+ {
+ // Already present
+ return;
+ }
+ } // for itr - Chunks[]
+ m_Chunks.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
+}
+
+
+
+
+
+void cChunkStay::Remove(int a_ChunkX, int a_ChunkZ)
+{
+ ASSERT(m_ChunkMap == NULL);
+
+ for (cChunkCoordsVector::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr)
+ {
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
+ {
+ // Found, un-"stay"
+ m_Chunks.erase(itr);
+ return;
+ }
+ } // for itr - m_Chunks[]
+}
+
+
+
+
+
+void cChunkStay::Enable(cChunkMap & a_ChunkMap)
+{
+ ASSERT(m_ChunkMap == NULL);
+
+ m_ChunkMap = &a_ChunkMap;
+ a_ChunkMap.AddChunkStay(*this);
+ m_OutstandingChunks = m_Chunks;
+}
+
+
+
+
+
+void cChunkStay::Disable(void)
+{
+ ASSERT(m_ChunkMap != NULL);
+
+ m_ChunkMap->DelChunkStay(*this);
+ m_ChunkMap = NULL;
+}
+
+
+
+
+
+void cChunkStay::ChunkAvailable(int a_ChunkX, int a_ChunkZ)
+{
+ // Check if this is a chunk that we want:
+ bool IsMine = false;
+ for (cChunkCoordsVector::const_iterator itr = m_OutstandingChunks.begin(), end = m_OutstandingChunks.end(); itr != end; ++itr)
+ {
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
+ {
+ m_OutstandingChunks.erase(itr);
+ IsMine = true;
+ break;
+ }
+ } // for itr - m_OutstandingChunks[]
+ if (!IsMine)
+ {
+ return;
+ }
+
+ // Call the appropriate callbacks:
+ OnChunkAvailable(a_ChunkX, a_ChunkZ);
+ if (m_OutstandingChunks.empty())
+ {
+ OnAllChunksAvailable();
+ }
+}
+
+
+
+
diff --git a/src/ChunkStay.h b/src/ChunkStay.h
new file mode 100644
index 000000000..6eb8e1669
--- /dev/null
+++ b/src/ChunkStay.h
@@ -0,0 +1,92 @@
+
+// ChunkStay.h
+
+/* Declares the cChunkStay class representing a base for classes that want to wait for certain chunks to load,
+then do some action on them. While the object is enabled, the chunks contained within are locked and will
+not unload
+*/
+
+
+
+
+
+#pragma once
+
+
+
+
+
+// fwd
+class cChunkMap;
+
+
+
+
+
+/** 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.
+To optimize for speed, cChunkStay has an Enabled flag, it will "stay" the chunks only when enabled
+and it will refuse chunk-list manipulations when enabled.
+The object itself is not made thread-safe, it's supposed to be used from a single thread only.
+This class is abstract, the descendants are expected to provide the OnChunkAvailable() and
+the OnAllChunksAvailable() callback implementations. Note that those are called from the contexts of
+different threads' - the caller, the Loader or the Generator thread.
+*/
+class cChunkStay
+{
+public:
+ cChunkStay(void);
+ ~cChunkStay();
+
+ void Clear(void);
+
+ /** Adds a chunk to be locked from unloading.
+ To be used only while the ChunkStay object is not enabled. */
+ void Add (int a_ChunkX, int a_ChunkZ);
+
+ /** Releases the chunk so that it's no longer locked from unloading.
+ To be used only while the ChunkStay object is not enabled. */
+ void Remove(int a_ChunkX, int a_ChunkZ);
+
+ /** Enables the ChunkStay on the specified chunkmap, causing it to load and generate chunks.
+ All the contained chunks are queued for loading / generating. */
+ void Enable (cChunkMap & a_ChunkMap);
+
+ /** Disables the ChunkStay, the chunks are released and the ChunkStay
+ object can be edited with Add() and Remove() again*/
+ void Disable(void);
+
+ /** Returns all the chunks that should be kept */
+ const cChunkCoordsVector & GetChunks(void) const { return m_Chunks; }
+
+ /** Called when a specific chunk become available. */
+ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) = 0;
+
+ /** Caled once all of the contained chunks are available. */
+ virtual void OnAllChunksAvailable(void) = 0;
+
+protected:
+
+ friend class cChunkMap;
+
+
+ /** The chunkmap where the object is enabled.
+ Valid only after call to Enable() and before Disable(). */
+ cChunkMap * m_ChunkMap;
+
+ /** The list of chunks to lock from unloading. */
+ cChunkCoordsVector m_Chunks;
+
+ /** The chunks that still need loading */
+ cChunkCoordsVector m_OutstandingChunks;
+
+
+ /** Called by cChunkMap when a chunk is available, checks m_NumLoaded and triggers the appropriate callbacks.
+ May be called for chunks outside this ChunkStay. */
+ void ChunkAvailable(int a_ChunkX, int a_ChunkZ);
+} ;
+
+
+
+
+
diff --git a/src/LightingThread.cpp b/src/LightingThread.cpp
index a823c08cc..b665066ee 100644
--- a/src/LightingThread.cpp
+++ b/src/LightingThread.cpp
@@ -6,6 +6,7 @@
#include "Globals.h"
#include "LightingThread.h"
#include "ChunkMap.h"
+#include "ChunkStay.h"
#include "World.h"
@@ -109,9 +110,14 @@ void cLightingThread::Stop(void)
{
{
cCSLock Lock(m_CS);
- for (sItems::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr)
+ for (cChunkStays::iterator itr = m_PendingQueue.begin(), end = m_PendingQueue.end(); itr != end; ++itr)
{
- delete itr->m_ChunkStay;
+ delete *itr;
+ }
+ m_PendingQueue.clear();
+ for (cChunkStays::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr)
+ {
+ delete *itr;
}
m_Queue.clear();
}
@@ -129,25 +135,12 @@ void cLightingThread::QueueChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback
{
ASSERT(m_World != NULL); // Did you call Start() properly?
- cChunkStay * ChunkStay = new cChunkStay(m_World);
- ChunkStay->Add(a_ChunkX + 1, ZERO_CHUNK_Y, a_ChunkZ + 1);
- ChunkStay->Add(a_ChunkX + 1, ZERO_CHUNK_Y, a_ChunkZ);
- ChunkStay->Add(a_ChunkX + 1, ZERO_CHUNK_Y, a_ChunkZ - 1);
- ChunkStay->Add(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ + 1);
- ChunkStay->Add(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
- ChunkStay->Add(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ - 1);
- ChunkStay->Add(a_ChunkX - 1, ZERO_CHUNK_Y, a_ChunkZ + 1);
- ChunkStay->Add(a_ChunkX - 1, ZERO_CHUNK_Y, a_ChunkZ);
- ChunkStay->Add(a_ChunkX - 1, ZERO_CHUNK_Y, a_ChunkZ - 1);
- ChunkStay->Enable();
- ChunkStay->Load();
+ cChunkStay * ChunkStay = new cLightingChunkStay(*this, a_ChunkX, a_ChunkZ, a_CallbackAfter);
+ ChunkStay->Enable(*m_World->GetChunkMap());
+ // The ChunkStay will enqueue itself using the QueueChunkStay() once it is fully loaded
+ // In the meantime, put it into the PendingQueue so that it can be removed when stopping the thread
cCSLock Lock(m_CS);
- m_Queue.push_back(sItem(a_ChunkX, a_ChunkZ, ChunkStay, a_CallbackAfter));
- if (m_Queue.size() > WARN_ON_QUEUE_SIZE)
- {
- LOGINFO("Lighting thread overloaded, %d items in queue", m_Queue.size());
- }
- m_evtItemAdded.Set();
+ m_PendingQueue.push_back(ChunkStay);
}
@@ -157,7 +150,7 @@ void cLightingThread::QueueChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback
void cLightingThread::WaitForQueueEmpty(void)
{
cCSLock Lock(m_CS);
- while (!m_ShouldTerminate && (!m_Queue.empty() || !m_PostponedQueue.empty()))
+ while (!m_ShouldTerminate && (!m_Queue.empty() || !m_PendingQueue.empty()))
{
cCSUnlock Unlock(Lock);
m_evtQueueEmpty.Wait();
@@ -171,43 +164,7 @@ void cLightingThread::WaitForQueueEmpty(void)
size_t cLightingThread::GetQueueLength(void)
{
cCSLock Lock(m_CS);
- return m_Queue.size() + m_PostponedQueue.size();
-}
-
-
-
-
-
-void cLightingThread::ChunkReady(int a_ChunkX, int a_ChunkZ)
-{
- // Check all the items in the m_PostponedQueue, if the chunk is their neighbor, move the item to m_Queue
-
- bool NewlyAdded = false;
- {
- cCSLock Lock(m_CS);
- for (sItems::iterator itr = m_PostponedQueue.begin(); itr != m_PostponedQueue.end(); )
- {
- if (
- (itr->x - a_ChunkX >= -1) && (itr->x - a_ChunkX <= 1) &&
- (itr->z - a_ChunkZ >= -1) && (itr->z - a_ChunkZ <= 1)
- )
- {
- // It is a neighbor
- m_Queue.push_back(*itr);
- itr = m_PostponedQueue.erase(itr);
- NewlyAdded = true;
- }
- else
- {
- ++itr;
- }
- } // for itr - m_PostponedQueue[]
- } // Lock(m_CS)
-
- if (NewlyAdded)
- {
- m_evtItemAdded.Set(); // Notify the thread it has some work to do
- }
+ return m_Queue.size() + m_PendingQueue.size();
}
@@ -233,14 +190,14 @@ void cLightingThread::Execute(void)
}
// Process one items from the queue:
- sItem Item;
+ cLightingChunkStay * Item;
{
cCSLock Lock(m_CS);
if (m_Queue.empty())
{
continue;
}
- Item = m_Queue.front();
+ Item = (cLightingChunkStay *)m_Queue.front();
m_Queue.pop_front();
if (m_Queue.empty())
{
@@ -248,7 +205,7 @@ void cLightingThread::Execute(void)
}
} // CSLock(m_CS)
- LightChunk(Item);
+ LightChunk(*Item);
}
}
@@ -257,23 +214,11 @@ void cLightingThread::Execute(void)
-void cLightingThread::LightChunk(cLightingThread::sItem & a_Item)
+void cLightingThread::LightChunk(cLightingChunkStay & a_Item)
{
cChunkDef::BlockNibbles BlockLight, SkyLight;
- if (!ReadChunks(a_Item.x, a_Item.z))
- {
- // Neighbors not available. Re-queue in the postponed queue
- cCSLock Lock(m_CS);
- m_PostponedQueue.push_back(a_Item);
- return;
- }
-
- /*
- // DEBUG: torch somewhere:
- m_BlockTypes[19 + 24 * cChunkDef::Width * 3 + (m_HeightMap[24 + 24 * cChunkDef::Width * 3] / 2) * BlocksPerYLayer] = E_BLOCK_TORCH;
- // m_HeightMap[24 + 24 * cChunkDef::Width * 3]++;
- */
+ ReadChunks(a_Item.m_ChunkX, a_Item.m_ChunkZ);
PrepareBlockLight();
CalcLight(m_BlockLight);
@@ -339,13 +284,13 @@ void cLightingThread::LightChunk(cLightingThread::sItem & a_Item)
CompressLight(m_BlockLight, BlockLight);
CompressLight(m_SkyLight, SkyLight);
- m_World->ChunkLighted(a_Item.x, a_Item.z, BlockLight, SkyLight);
+ m_World->ChunkLighted(a_Item.m_ChunkX, a_Item.m_ChunkZ, BlockLight, SkyLight);
- if (a_Item.m_Callback != NULL)
+ if (a_Item.m_CallbackAfter != NULL)
{
- a_Item.m_Callback->Call(a_Item.x, a_Item.z);
+ a_Item.m_CallbackAfter->Call(a_Item.m_ChunkX, a_Item.m_ChunkZ);
}
- delete a_Item.m_ChunkStay;
+ delete &a_Item;
}
@@ -561,3 +506,51 @@ void cLightingThread::CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_Ch
+
+void cLightingThread::QueueChunkStay(cLightingChunkStay & a_ChunkStay)
+{
+ // Move the ChunkStay from the Pending queue to the lighting queue.
+ {
+ cCSLock Lock(m_CS);
+ m_PendingQueue.remove(&a_ChunkStay);
+ m_Queue.push_back(&a_ChunkStay);
+ }
+ m_evtItemAdded.Set();
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cLightingThread::cLightingChunkStay:
+
+cLightingThread::cLightingChunkStay::cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter) :
+ m_LightingThread(a_LightingThread),
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_CallbackAfter(a_CallbackAfter)
+{
+ Add(a_ChunkX + 1, a_ChunkZ + 1);
+ Add(a_ChunkX + 1, a_ChunkZ);
+ Add(a_ChunkX + 1, a_ChunkZ - 1);
+ Add(a_ChunkX, a_ChunkZ + 1);
+ Add(a_ChunkX, a_ChunkZ);
+ Add(a_ChunkX, a_ChunkZ - 1);
+ Add(a_ChunkX - 1, a_ChunkZ + 1);
+ Add(a_ChunkX - 1, a_ChunkZ);
+ Add(a_ChunkX - 1, a_ChunkZ - 1);
+}
+
+
+
+
+
+void cLightingThread::cLightingChunkStay::OnAllChunksAvailable(void)
+{
+ m_LightingThread.QueueChunkStay(*this);
+}
+
+
+
+
diff --git a/src/LightingThread.h b/src/LightingThread.h
index d8ce59f01..0e17c485f 100644
--- a/src/LightingThread.h
+++ b/src/LightingThread.h
@@ -33,6 +33,7 @@ Chunks from m_PostponedQueue are moved back into m_Queue when their neighbors ge
#include "OSSupport/IsThread.h"
#include "ChunkDef.h"
+#include "ChunkStay.h"
@@ -41,9 +42,6 @@ Chunks from m_PostponedQueue are moved back into m_Queue when their neighbors ge
// fwd: "cWorld.h"
class cWorld;
-// fwd: "cChunkMap.h"
-class cChunkStay;
-
@@ -62,43 +60,49 @@ public:
void Stop(void);
- /// Queues the entire chunk for lighting
+ /** Queues the entire chunk for lighting */
void QueueChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter = NULL);
- /// Blocks until the queue is empty or the thread is terminated
+ /** Blocks until the queue is empty or the thread is terminated */
void WaitForQueueEmpty(void);
size_t GetQueueLength(void);
- /// Called from cWorld when a chunk gets valid. Chunks in m_PostponedQueue may need moving into m_Queue
- void ChunkReady(int a_ChunkX, int a_ChunkZ);
-
protected:
- struct sItem
+ class cLightingChunkStay :
+ public cChunkStay
{
- int x, z;
- cChunkStay * m_ChunkStay;
- cChunkCoordCallback * m_Callback;
+ public:
+ cLightingThread & m_LightingThread;
+ int m_ChunkX;
+ int m_ChunkZ;
+ cChunkCoordCallback * m_CallbackAfter;
- sItem(void) {} // empty default constructor needed
- sItem(int a_X, int a_Z, cChunkStay * a_ChunkStay, cChunkCoordCallback * a_Callback) :
- x(a_X),
- z(a_Z),
- m_ChunkStay(a_ChunkStay),
- m_Callback(a_Callback)
- {
- }
+ cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter);
+
+ protected:
+ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override {}
+ virtual void OnAllChunksAvailable(void) override;
} ;
- typedef std::list<sItem> sItems;
+ typedef std::list<cChunkStay *> cChunkStays;
+
- cWorld * m_World;
+ cWorld * m_World;
+
+ /** The mutex to protect m_Queue and m_PendingQueue */
cCriticalSection m_CS;
- sItems m_Queue;
- sItems m_PostponedQueue; // Chunks that have been postponed due to missing neighbors
- cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
- cEvent m_evtQueueEmpty; // Set when the queue gets empty
+
+ /** The ChunkStays that are loaded and are waiting to be lit. */
+ cChunkStays m_Queue;
+
+ /** The ChunkStays that are waiting for load. Used for stopping the thread. */
+ cChunkStays m_PendingQueue;
+
+ cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread
+ cEvent m_evtQueueEmpty; // Set when the queue gets empty
+
// Buffers for the 3x3 chunk data
// These buffers alone are 1.7 MiB in size, therefore they cannot be located on the stack safely - some architectures may have only 1 MiB for stack, or even less
@@ -124,29 +128,29 @@ protected:
virtual void Execute(void) override;
- /// Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk
- void LightChunk(sItem & a_Item);
+ /** Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk */
+ void LightChunk(cLightingChunkStay & a_Item);
- /// Prepares m_BlockTypes and m_HeightMap data; returns false if any of the chunks fail. Zeroes out the light arrays
+ /** Prepares m_BlockTypes and m_HeightMap data; returns false if any of the chunks fail. Zeroes out the light arrays */
bool ReadChunks(int a_ChunkX, int a_ChunkZ);
- /// Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight
+ /** Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight */
void PrepareSkyLight(void);
- /// Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight
+ /** Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight */
void PrepareBlockLight(void);
- /// Calculates light in the light array specified, using stored seeds
+ /** Calculates light in the light array specified, using stored seeds */
void CalcLight(NIBBLETYPE * a_Light);
- /// Does one step in the light calculation - one seed propagation and seed recalculation
+ /** Does one step in the light calculation - one seed propagation and seed recalculation */
void CalcLightStep(
NIBBLETYPE * a_Light,
int a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn,
int & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
);
- /// Compresses from 1-block-per-byte (faster calc) into 2-blocks-per-byte (MC storage):
+ /** Compresses from 1-block-per-byte (faster calc) into 2-blocks-per-byte (MC storage): */
void CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_ChunkLight);
inline void PropagateLight(
@@ -174,6 +178,10 @@ protected:
}
}
+ /** Queues a chunkstay that has all of its chunks loaded.
+ Called by cLightingChunkStay when all of its chunks are loaded. */
+ void QueueChunkStay(cLightingChunkStay & a_ChunkStay);
+
} ;
diff --git a/src/World.cpp b/src/World.cpp
index ebdd3fb06..dfc186639 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2145,9 +2145,6 @@ void cWorld::SetChunkData(
{
m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkZ);
}
-
- // Notify the lighting thread that the chunk has become valid (in case it is a neighbor of a postponed chunk):
- m_Lighting.ChunkReady(a_ChunkX, a_ChunkZ);
}
@@ -2561,15 +2558,6 @@ bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, co
-void cWorld::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
-{
- m_ChunkMap->ChunksStay(a_Chunks, a_Stay);
-}
-
-
-
-
-
void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
{
m_ChunkMap->MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
diff --git a/src/World.h b/src/World.h
index d436e7adf..b82bdc67c 100644
--- a/src/World.h
+++ b/src/World.h
@@ -308,9 +308,6 @@ public:
/** Sets the command block command. Returns true if command changed. */
bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export
- /** Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable. To be used only by cChunkStay! */
- void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true);
-
/** Regenerate the given chunk: */
void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export