diff options
author | madmaxoft <github@xoft.cz> | 2014-02-08 21:55:21 +0100 |
---|---|---|
committer | madmaxoft <github@xoft.cz> | 2014-02-08 21:55:21 +0100 |
commit | ea71bfa9b645cda80b7d4364c675ebaee8db8353 (patch) | |
tree | 8db9fc2cd467e32bebd2aae4aaac2208fee60c2f | |
parent | Merge pull request #653 from mc-server/RedstoneSimulator (diff) | |
download | cuberite-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.cpp | 1 | ||||
-rw-r--r-- | src/Chunk.h | 110 | ||||
-rw-r--r-- | src/ChunkDef.h | 1 | ||||
-rw-r--r-- | src/ChunkMap.cpp | 185 | ||||
-rw-r--r-- | src/ChunkMap.h | 199 | ||||
-rw-r--r-- | src/ChunkStay.cpp | 136 | ||||
-rw-r--r-- | src/ChunkStay.h | 92 | ||||
-rw-r--r-- | src/LightingThread.cpp | 151 | ||||
-rw-r--r-- | src/LightingThread.h | 76 | ||||
-rw-r--r-- | src/World.cpp | 12 | ||||
-rw-r--r-- | src/World.h | 3 |
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 |