summaryrefslogtreecommitdiffstats
path: root/source/Chunk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Chunk.cpp')
-rw-r--r--source/Chunk.cpp497
1 files changed, 245 insertions, 252 deletions
diff --git a/source/Chunk.cpp b/source/Chunk.cpp
index db533f642..c7bac879a 100644
--- a/source/Chunk.cpp
+++ b/source/Chunk.cpp
@@ -30,6 +30,9 @@
#include "PluginManager.h"
#include "Blocks/BlockHandler.h"
#include "Simulator/FluidSimulator.h"
+#include "MobCensus.h"
+#include "MobSpawner.h"
+
#include <json/json.h>
@@ -429,6 +432,133 @@ void cChunk::Stay(bool a_Stay)
+void cChunk::CollectMobCensus(cMobCensus& toFill)
+{
+ toFill.CollectSpawnableChunk(*this);
+ std::list<const Vector3d*> playerPositions;
+ cPlayer* currentPlayer;
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(), end = m_LoadedByClient.end(); itr != end; ++itr)
+ {
+ currentPlayer = (*itr)->GetPlayer();
+ playerPositions.push_back(&(currentPlayer->GetPosition()));
+ }
+
+ Vector3d currentPosition;
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
+ {
+ //LOGD("Counting entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
+ if ((*itr)->IsMob())
+ {
+ cMonster& Monster = (cMonster&)(**itr);
+ currentPosition = Monster.GetPosition();
+ for (std::list<const Vector3d*>::const_iterator itr2 = playerPositions.begin(); itr2 != playerPositions.end(); itr2 ++)
+ {
+ toFill.CollectMob(Monster,*this,(currentPosition-**itr2).SqrLength());
+ }
+ }
+ } // for itr - m_Entitites[]
+}
+
+
+
+
+void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a_MaxY, int a_MaxZ)
+{
+ ASSERT(a_MaxX * a_MaxY * a_MaxZ * 8 < 0x00ffffff);
+ int Random = m_World->GetTickRandomNumber(0x00ffffff);
+ a_X = Random % (a_MaxX * 2);
+ a_Y = (Random / (a_MaxX * 2)) % (a_MaxY * 2);
+ a_Z = ((Random / (a_MaxX * 2)) / (a_MaxY * 2)) % (a_MaxZ * 2);
+ a_X /= 2;
+ a_Y /= 2;
+ a_Z /= 2;
+}
+
+
+
+
+
+void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
+{
+ // MG TODO : check if this kind of optimization (only one random call) is still needed
+ // MG TODO : if so propagate it
+
+ getThreeRandomNumber(a_X, a_Y, a_Z, Width, Height-2, Width);
+ a_Y++;
+}
+
+
+
+
+
+void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner)
+{
+ int Center_X,Center_Y,Center_Z;
+ getRandomBlockCoords(Center_X,Center_Y,Center_Z);
+
+ BLOCKTYPE PackCenterBlock = GetBlock(Center_X, Center_Y, Center_Z);
+ if (a_MobSpawner.CheckPackCenter(PackCenterBlock))
+ {
+ a_MobSpawner.NewPack();
+ int NumberOfTries = 0;
+ int NumberOfSuccess = 0;
+ int MaxNbOfSuccess = 4; // this can be changed during the process for Wolves and Ghass
+ while (NumberOfTries < 12 && NumberOfSuccess < MaxNbOfSuccess)
+ {
+ const int HorizontalRange = 20; // MG TODO : relocate
+ const int VerticalRange = 0; // MG TODO : relocate
+ int Try_X, Try_Y, Try_Z;
+ getThreeRandomNumber(Try_X, Try_Y, Try_Z, 2*HorizontalRange+1 , 2*VerticalRange+1 , 2*HorizontalRange+1);
+ Try_X -= HorizontalRange;
+ Try_Y -= VerticalRange;
+ Try_Z -= HorizontalRange;
+ Try_X += Center_X;
+ Try_Y += Center_Y;
+ Try_Z += Center_Z;
+
+ ASSERT(Try_Y > 0);
+ ASSERT(Try_Y < cChunkDef::Height-1);
+
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ BLOCKTYPE BlockType_below;
+ NIBBLETYPE BlockMeta_below;
+ BLOCKTYPE BlockType_above;
+ NIBBLETYPE BlockMeta_above;
+ if (UnboundedRelGetBlock(Try_X, Try_Y , Try_Z, BlockType, BlockMeta) &&
+ UnboundedRelGetBlock(Try_X, Try_Y-1, Try_Z, BlockType_below, BlockMeta_below)&&
+ UnboundedRelGetBlock(Try_X, Try_Y+1, Try_Z, BlockType_above, BlockMeta_above)
+ )
+ {
+ EMCSBiome Biome = m_ChunkMap->GetBiomeAt (Try_X, Try_Z);
+ // MG TODO :
+ // Moon cycle (for slime)
+ // check player and playerspawn presence < 24 blocks
+ // check mobs presence on the block
+
+ // MG TODO: fix the "light" thing, I'm pretty sure that UnboundedRelGetBlock s not returning the right thing
+
+ // MG TODO : check that "Level" really means Y
+ cEntity* newMob = a_MobSpawner.TryToSpawnHere(BlockType, BlockMeta, BlockType_below, BlockMeta_below, BlockType_above, BlockMeta_above, Biome, Try_Y, MaxNbOfSuccess);
+ if (newMob)
+ {
+ int WorldX, WorldY, WorldZ;
+ PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ);
+ newMob->SetPosition(WorldX, WorldY, WorldZ);
+ LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ);
+ NumberOfSuccess++;
+ }
+ }
+
+ NumberOfTries++;
+ }
+ }
+
+}
+
+
+
+
void cChunk::Tick(float a_Dt)
{
@@ -457,10 +587,14 @@ void cChunk::Tick(float a_Dt)
m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty;
}
- // Tick all entities in this chunk:
+ // Tick all entities in this chunk (except mobs):
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
- (*itr)->Tick(a_Dt, *this);
+ // Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players)
+ if (!((*itr)->IsMob()))
+ {
+ (*itr)->Tick(a_Dt, *this);
+ }
} // for itr - m_Entitites[]
// Remove all entities that were scheduled for removal:
@@ -923,45 +1057,14 @@ bool cChunk::UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelY);
return false;
}
-
- // Is it in this chunk?
- if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width))
- {
- if (!IsValid())
- {
- return false;
- }
- int BlockIdx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
- a_BlockType = GetBlock(BlockIdx);
- a_BlockMeta = GetMeta(BlockIdx);
- return true;
- }
-
- // Not in this chunk, try walking the neighbors first:
- if ((a_RelX < 0) && (m_NeighborXM != NULL))
- {
- return m_NeighborXM->UnboundedRelGetBlock(a_RelX + cChunkDef::Width, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- }
- if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL))
- {
- return m_NeighborXP->UnboundedRelGetBlock(a_RelX - cChunkDef::Width, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- }
- if ((a_RelZ < 0) && (m_NeighborZM != NULL))
- {
- return m_NeighborZM->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + cChunkDef::Width, a_BlockType, a_BlockMeta);
- }
- if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- return m_NeighborZP->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ - cChunkDef::Width, a_BlockType, a_BlockMeta);
+ // The chunk is not available, bail out
+ return false;
}
-
- // Neighbors not available, use the chunkmap to locate the chunk:
- return m_ChunkMap->LockedGetBlock(
- m_PosX * cChunkDef::Width + a_RelX,
- ZERO_CHUNK_Y * cChunkDef::Height + a_RelY,
- m_PosZ * cChunkDef::Width + a_RelZ,
- a_BlockType, a_BlockMeta
- );
+ Chunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
+ return true;
}
@@ -975,44 +1078,14 @@ bool cChunk::UnboundedRelGetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKT
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelY);
return false;
}
-
- // Is it in this chunk?
- if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width))
- {
- if (!IsValid())
- {
- return false;
- }
- int BlockIdx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
- a_BlockType = GetBlock(BlockIdx);
- return true;
- }
-
- // Not in this chunk, try walking the neighbors first:
- if ((a_RelX < 0) && (m_NeighborXM != NULL))
- {
- return m_NeighborXM->UnboundedRelGetBlockType(a_RelX + cChunkDef::Width, a_RelY, a_RelZ, a_BlockType);
- }
- if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- return m_NeighborXP->UnboundedRelGetBlockType(a_RelX - cChunkDef::Width, a_RelY, a_RelZ, a_BlockType);
- }
- if ((a_RelZ < 0) && (m_NeighborZM != NULL))
- {
- return m_NeighborZM->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ + cChunkDef::Width, a_BlockType);
- }
- if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL))
- {
- return m_NeighborZP->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ - cChunkDef::Width, a_BlockType);
+ // The chunk is not available, bail out
+ return false;
}
-
- // Neighbors not available, use the chunkmap to locate the chunk:
- return m_ChunkMap->LockedGetBlockType(
- m_PosX * cChunkDef::Width + a_RelX,
- ZERO_CHUNK_Y * cChunkDef::Height + a_RelY,
- m_PosZ * cChunkDef::Width + a_RelZ,
- a_BlockType
- );
+ a_BlockType = Chunk->GetBlock(a_RelX, a_RelY, a_RelZ);
+ return true;
}
@@ -1026,44 +1099,56 @@ bool cChunk::UnboundedRelGetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLE
LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelY);
return false;
}
-
- // Is it in this chunk?
- if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- if (!IsValid())
- {
- return false;
- }
- int BlockIdx = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
- a_BlockMeta = GetMeta(BlockIdx);
- return true;
+ // The chunk is not available, bail out
+ return false;
}
+ a_BlockMeta = Chunk->GetMeta(a_RelX, a_RelY, a_RelZ);
+ return true;
+}
+
+
- // Not in this chunk, try walking the neighbors first:
- if ((a_RelX < 0) && (m_NeighborXM != NULL))
+
+
+bool cChunk::UnboundedRelGetBlockBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockBlockLight) const
+{
+ if ((a_RelY < 0) || (a_RelY >= cChunkDef::Height))
{
- return m_NeighborXM->UnboundedRelGetBlockMeta(a_RelX + cChunkDef::Width, a_RelY, a_RelZ, a_BlockMeta);
+ LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelY);
+ return false;
}
- if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- return m_NeighborXP->UnboundedRelGetBlockMeta(a_RelX - cChunkDef::Width, a_RelY, a_RelZ, a_BlockMeta);
+ // The chunk is not available, bail out
+ return false;
}
- if ((a_RelZ < 0) && (m_NeighborZM != NULL))
+ a_BlockBlockLight = Chunk->GetBlockLight(a_RelX, a_RelY, a_RelZ);
+ return true;
+}
+
+
+
+
+
+bool cChunk::UnboundedRelGetBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockSkyLight) const
+{
+ if ((a_RelY < 0) || (a_RelY >= cChunkDef::Height))
{
- return m_NeighborZM->UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ + cChunkDef::Width, a_BlockMeta);
+ LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelY);
+ return false;
}
- if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- return m_NeighborZP->UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ - cChunkDef::Width, a_BlockMeta);
+ // The chunk is not available, bail out
+ return false;
}
-
- // Neighbors not available, use the chunkmap to locate the chunk:
- return m_ChunkMap->LockedGetBlockMeta(
- m_PosX * cChunkDef::Width + a_RelX,
- ZERO_CHUNK_Y * cChunkDef::Height + a_RelY,
- m_PosZ * cChunkDef::Width + a_RelZ,
- a_BlockMeta
- );
+ a_BlockSkyLight = Chunk->GetSkyLight(a_RelX, a_RelY, a_RelZ);
+ return true;
}
@@ -1077,44 +1162,15 @@ bool cChunk::UnboundedRelSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
LOGWARNING("UnboundedRelSetBlock(): requesting a block with a_RelY out of range: %d", a_RelY);
return false;
}
-
- // Is it in this chunk?
- if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- if (!IsValid())
- {
- return false;
- }
- SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- return true;
- }
-
- // Not in this chunk, try walking the neighbors first:
- if ((a_RelX < 0) && (m_NeighborXM != NULL))
- {
- return m_NeighborXM->UnboundedRelSetBlock(a_RelX + cChunkDef::Width, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- }
- if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL))
- {
- return m_NeighborXP->UnboundedRelSetBlock(a_RelX - cChunkDef::Width, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- }
- if ((a_RelZ < 0) && (m_NeighborZM != NULL))
- {
- return m_NeighborZM->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ + cChunkDef::Width, a_BlockType, a_BlockMeta);
- }
- if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL))
- {
- return m_NeighborZP->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ - cChunkDef::Width, a_BlockType, a_BlockMeta);
+ // The chunk is not available, bail out
+ return false;
}
-
- // Neighbors not available, use the chunkmap to locate the chunk:
- return m_ChunkMap->LockedSetBlock(
- m_PosX * cChunkDef::Width + a_RelX,
- ZERO_CHUNK_Y * cChunkDef::Height + a_RelY,
- m_PosZ * cChunkDef::Width + a_RelZ,
- a_BlockType, a_BlockMeta
- );
-}
+ Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
+ return true;
+}
@@ -1127,43 +1183,14 @@ bool cChunk::UnboundedRelFastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKT
LOGWARNING("UnboundedRelFastSetBlock(): requesting a block with a_RelY out of range: %d", a_RelY);
return false;
}
-
- // Is it in this chunk?
- if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width))
- {
- if (!IsValid())
- {
- return false;
- }
- FastSetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- return true;
- }
-
- // Not in this chunk, try walking the neighbors first:
- if ((a_RelX < 0) && (m_NeighborXM != NULL))
- {
- return m_NeighborXM->UnboundedRelFastSetBlock(a_RelX + cChunkDef::Width, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- }
- if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
{
- return m_NeighborXP->UnboundedRelFastSetBlock(a_RelX - cChunkDef::Width, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
- }
- if ((a_RelZ < 0) && (m_NeighborZM != NULL))
- {
- return m_NeighborZM->UnboundedRelFastSetBlock(a_RelX, a_RelY, a_RelZ + cChunkDef::Width, a_BlockType, a_BlockMeta);
- }
- if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL))
- {
- return m_NeighborZP->UnboundedRelFastSetBlock(a_RelX, a_RelY, a_RelZ - cChunkDef::Width, a_BlockType, a_BlockMeta);
+ // The chunk is not available, bail out
+ return false;
}
-
- // Neighbors not available, use the chunkmap to locate the chunk:
- return m_ChunkMap->LockedFastSetBlock(
- m_PosX * cChunkDef::Width + a_RelX,
- ZERO_CHUNK_Y * cChunkDef::Height + a_RelY,
- m_PosZ * cChunkDef::Width + a_RelZ,
- a_BlockType, a_BlockMeta
- );
+ Chunk->FastSetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
+ return true;
}
@@ -1177,44 +1204,18 @@ void cChunk::UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ)
// Outside of chunkmap
return;
}
-
- // Is it in this chunk?
- if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width))
- {
- QueueTickBlock(a_RelX, a_RelY, a_RelZ);
- return;
- }
-
- // Not in this chunk, try walking the neighbors first:
- if ((a_RelX < 0) && (m_NeighborXM != NULL))
- {
- m_NeighborXM->UnboundedQueueTickBlock(a_RelX + cChunkDef::Width, a_RelY, a_RelZ);
- return;
- }
- if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL))
- {
- m_NeighborXP->UnboundedQueueTickBlock(a_RelX - cChunkDef::Width, a_RelY, a_RelZ);
- return;
- }
- if ((a_RelZ < 0) && (m_NeighborZM != NULL))
- {
- m_NeighborZM->UnboundedQueueTickBlock(a_RelX, a_RelY, a_RelZ + cChunkDef::Width);
- return;
- }
- if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL))
+ cChunk * Chunk = GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((Chunk != NULL) && Chunk->IsValid())
{
- m_NeighborZP->UnboundedQueueTickBlock(a_RelX, a_RelY, a_RelZ - cChunkDef::Width);
- return;
+ Chunk->QueueTickBlock(a_RelX, a_RelY, a_RelZ);
}
-
- // Neighbors not available, ignore altogether
}
-int cChunk::GetHeight( int a_X, int a_Z )
+int cChunk::GetHeight(int a_X, int a_Z)
{
ASSERT((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width));
@@ -2340,66 +2341,58 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
-cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ)
+cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) const
{
- bool ReturnThis = true;
- int RelX = a_RelX;
+ cChunk * ToReturn = const_cast<cChunk *>(this);
+
+ // The most common case: inside this chunk:
+ if (
+ (a_RelX >= 0) && (a_RelX < Width) &&
+ (a_RelZ >= 0) && (a_RelZ < Width)
+ )
+ {
+ return ToReturn;
+ }
+
+ // Request for a different chunk, calculate chunk offset:
+ int RelX = a_RelX; // Make a local copy of the coords (faster access)
int RelZ = a_RelZ;
- if (a_RelX < 0)
+ while ((RelX >= Width) && (ToReturn != NULL))
{
- if (m_NeighborXM != NULL)
- {
- RelX = a_RelX + cChunkDef::Width;
- cChunk * Candidate = m_NeighborXM->GetRelNeighborChunkAdjustCoords(RelX, RelZ);
- if (Candidate != NULL)
- {
- a_RelX = RelX;
- a_RelZ = RelZ;
- return Candidate;
- }
- }
- // Going X-first failed, but if the request is crossing Z as well, let's try the Z-first later on.
- ReturnThis = false;
+ RelX -= Width;
+ ToReturn = ToReturn->m_NeighborXP;
}
- else if (a_RelX >= cChunkDef::Width)
+ while ((RelX < 0) && (ToReturn != NULL))
{
- if (m_NeighborXP != NULL)
- {
- RelX = a_RelX - cChunkDef::Width;
- cChunk * Candidate = m_NeighborXP->GetRelNeighborChunkAdjustCoords(RelX, RelZ);
- if (Candidate != NULL)
- {
- a_RelX = RelX;
- a_RelZ = RelZ;
- return Candidate;
- }
- }
- // Going X-first failed, but if the request is crossing Z as well, let's try the Z-first later on.
- ReturnThis = false;
+ RelX += Width;
+ ToReturn = ToReturn->m_NeighborXM;
}
-
- if (a_RelZ < 0)
+ while ((RelZ >= Width) && (ToReturn != NULL))
{
- if (m_NeighborZM != NULL)
- {
- a_RelZ += cChunkDef::Width;
- return m_NeighborZM->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
- // For requests crossing both X and Z, the X-first way has been already tried
- }
- return NULL;
+ RelZ -= Width;
+ ToReturn = ToReturn->m_NeighborZP;
}
- else if (a_RelZ >= cChunkDef::Width)
+ while ((RelZ < 0) && (ToReturn != NULL))
{
- if (m_NeighborZP != NULL)
- {
- a_RelZ -= cChunkDef::Width;
- return m_NeighborZP->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
- // For requests crossing both X and Z, the X-first way has been already tried
- }
- return NULL;
+ RelZ += Width;
+ ToReturn = ToReturn->m_NeighborZM;
+ }
+ if (ToReturn != NULL)
+ {
+ a_RelX = RelX;
+ a_RelZ = RelZ;
+ return ToReturn;
}
- return (ReturnThis ? this : NULL);
+ // The chunk cannot be walked through neighbors, find it through the chunkmap:
+ int AbsX = a_RelX + m_PosX * Width;
+ int AbsZ = a_RelZ + m_PosZ * Width;
+ int DstChunkX, DstChunkZ;
+ BlockToChunk(AbsX, AbsZ, DstChunkX, DstChunkZ);
+ ToReturn = m_ChunkMap->FindChunk(DstChunkX, DstChunkZ);
+ a_RelX = AbsX - DstChunkX * Width;
+ a_RelZ = AbsZ - DstChunkZ * Width;
+ return ToReturn;
}