diff options
Diffstat (limited to 'src/Chunk.cpp')
-rw-r--r-- | src/Chunk.cpp | 94 |
1 files changed, 72 insertions, 22 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 40ffff834..8b2655cc9 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -37,6 +37,7 @@ #include "MobSpawner.h" #include "BlockInServerPluginInterface.h" #include "SetChunkData.h" +#include "BoundingBox.h" #include "json/json.h" @@ -65,19 +66,18 @@ sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_Bloc // cChunk: cChunk::cChunk( - int a_ChunkX, int a_ChunkY, int a_ChunkZ, + int a_ChunkX, int a_ChunkZ, cChunkMap * a_ChunkMap, cWorld * a_World, cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP, cAllocationPool<cChunkData::sChunkSection> & a_Pool ) : - m_IsValid(false), + m_Presence(cpInvalid), m_IsLightValid(false), m_IsDirty(false), m_IsSaving(false), m_HasLoadFailed(false), m_StayCount(0), m_PosX(a_ChunkX), - m_PosY(a_ChunkY), m_PosZ(a_ChunkZ), m_World(a_World), m_ChunkMap(a_ChunkMap), @@ -165,11 +165,22 @@ cChunk::~cChunk() -void cChunk::SetValid(void) +void cChunk::SetPresence(cChunk::ePresence a_Presence) { - m_IsValid = true; - - m_World->GetChunkMap()->ChunkValidated(); + m_Presence = a_Presence; + if (a_Presence == cpPresent) + { + m_World->GetChunkMap()->ChunkValidated(); + } +} + + + + + +void cChunk::SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed) +{ + m_ShouldGenerateIfLoadFailed = a_ShouldGenerateIfLoadFailed; } @@ -178,6 +189,9 @@ void cChunk::SetValid(void) void cChunk::MarkRegenerating(void) { + // Set as queued again: + SetPresence(cpQueued); + // Tell all clients attached to this chunk that they want this chunk: for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) { @@ -191,7 +205,11 @@ void cChunk::MarkRegenerating(void) bool cChunk::CanUnload(void) { - return m_LoadedByClient.empty() && !m_IsDirty && (m_StayCount == 0); + return + m_LoadedByClient.empty() && // The chunk is not used by any client + !m_IsDirty && // The chunk has been saved properly or hasn't been touched since the load / gen + (m_StayCount == 0) && // The chunk is not in a ChunkStay + (m_Presence != cpQueued) ; // The chunk is not queued for loading / generating (otherwise multi-load / multi-gen could occur) } @@ -223,7 +241,7 @@ void cChunk::MarkSaved(void) void cChunk::MarkLoaded(void) { m_IsDirty = false; - SetValid(); + SetPresence(cpPresent); } @@ -232,12 +250,17 @@ void cChunk::MarkLoaded(void) void cChunk::MarkLoadFailed(void) { - if (m_IsValid) + ASSERT(m_Presence == cpQueued); + + // If the chunk is marked as needed, generate it: + if (m_ShouldGenerateIfLoadFailed) { - return; + m_World->GetGenerator().QueueGenerateChunk(m_PosX, m_PosZ, false); + } + else + { + m_Presence = cpInvalid; } - - m_HasLoadFailed = true; } @@ -246,6 +269,8 @@ void cChunk::MarkLoadFailed(void) void cChunk::GetAllData(cChunkDataCallback & a_Callback) { + ASSERT(m_Presence == cpPresent); + a_Callback.HeightMap(&m_HeightMap); a_Callback.BiomeData(&m_BiomeMap); @@ -272,6 +297,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData) { ASSERT(a_SetChunkData.IsHeightMapValid()); ASSERT(a_SetChunkData.AreBiomesValid()); + ASSERT(IsQueued()); memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap)); memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap)); @@ -317,7 +343,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData) CreateBlockEntities(); // Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize) - SetValid(); + SetPresence(cpPresent); // Wake up all simulators for their respective blocks: WakeUpSimulators(); @@ -653,7 +679,7 @@ void cChunk::MoveEntityToNewChunk(cEntity * a_Entity) cChunk * Neighbor = GetNeighborChunk(a_Entity->GetChunkX() * cChunkDef::Width, a_Entity->GetChunkZ() * cChunkDef::Width); if (Neighbor == NULL) { - Neighbor = m_ChunkMap->GetChunkNoLoad(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ()); + Neighbor = m_ChunkMap->GetChunkNoLoad(a_Entity->GetChunkX(), a_Entity->GetChunkZ()); if (Neighbor == NULL) { // TODO: What to do with this? @@ -1319,11 +1345,11 @@ void cChunk::CreateBlockEntities(void) case E_BLOCK_JUKEBOX: case E_BLOCK_FLOWER_POT: { - if (!HasBlockEntityAt(x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width)) + if (!HasBlockEntityAt(x + m_PosX * Width, y, z + m_PosZ * Width)) { m_BlockEntities.push_back(cBlockEntity::CreateByBlockType( BlockType, GetMeta(x, y, z), - x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width, m_World + x + m_PosX * Width, y, z + m_PosZ * Width, m_World )); } break; @@ -1960,6 +1986,30 @@ bool cChunk::ForEachEntity(cEntityCallback & a_Callback) +bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback) +{ + // The entity list is locked by the parent chunkmap's CS + for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2) + { + ++itr2; + cBoundingBox EntBox((*itr)->GetPosition(), (*itr)->GetWidth() / 2, (*itr)->GetHeight()); + if (!EntBox.DoesIntersect(a_Box)) + { + // The entity is not in the specified box + continue; + } + if (a_Callback.Item(*itr)) + { + return false; + } + } // for itr - m_Entitites[] + return true; +} + + + + + bool cChunk::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult) { // The entity list is locked by the parent chunkmap's CS @@ -2165,7 +2215,7 @@ bool cChunk::DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_Blo } } - if (a_Callback.Item((cRedstonePoweredEntity *)*itr)) + if (a_Callback.Item(dynamic_cast<cRedstonePoweredEntity *>(*itr))) // Needs dynamic_cast due to multiple inheritance { return false; } @@ -2603,7 +2653,7 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ) int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ; int ChunkX, ChunkZ; BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); - return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ); + return m_ChunkMap->GetChunkNoLoad(ChunkX, ChunkZ); } // Walk the neighbors: @@ -2993,7 +3043,7 @@ void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation -void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude) +void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) { for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) { @@ -3001,7 +3051,7 @@ void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src { continue; } - (*itr)->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount); + (*itr)->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount); } // for itr - LoadedByClient[] } @@ -3128,7 +3178,7 @@ void cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ) { - return Vector3i(m_PosX * Width + a_RelX, m_PosY * Height + a_RelY, m_PosZ * Width + a_RelZ); + return Vector3i(m_PosX * Width + a_RelX, a_RelY, m_PosZ * Width + a_RelZ); } |