summaryrefslogtreecommitdiffstats
path: root/src/Chunk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Chunk.cpp')
-rw-r--r--src/Chunk.cpp429
1 files changed, 227 insertions, 202 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 4703e4536..b83036b6d 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -34,6 +34,7 @@
#include "MobCensus.h"
#include "MobSpawner.h"
#include "BlockInServerPluginInterface.h"
+#include "SetChunkData.h"
#include "json/json.h"
@@ -41,15 +42,15 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// sSetBlock:
-sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) // absolute block position
- : x( a_BlockX )
- , y( a_BlockY )
- , z( a_BlockZ )
- , BlockType( a_BlockType )
- , BlockMeta( a_BlockMeta )
+sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) // absolute block position
+ : x( a_BlockX)
+ , y( a_BlockY)
+ , z( a_BlockZ)
+ , BlockType( a_BlockType)
+ , BlockMeta( a_BlockMeta)
{
cChunkDef::AbsoluteToRelative(x, y, z, ChunkX, ChunkZ);
}
@@ -58,11 +59,11 @@ 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_ChunkY, 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
@@ -87,7 +88,8 @@ cChunk::cChunk(
m_NeighborZM(a_NeighborZM),
m_NeighborZP(a_NeighborZP),
m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()),
- m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData())
+ m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()),
+ m_AlwaysTicked(0)
{
if (a_NeighborXM != NULL)
{
@@ -115,7 +117,7 @@ cChunk::~cChunk()
{
cPluginManager::Get()->CallHookChunkUnloaded(m_World, m_PosX, m_PosZ);
- // LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId() );
+ // LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId());
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
@@ -152,7 +154,9 @@ cChunk::~cChunk()
m_NeighborZP->m_NeighborZM = NULL;
}
delete m_WaterSimulatorData;
+ m_WaterSimulatorData = NULL;
delete m_LavaSimulatorData;
+ m_LavaSimulatorData = NULL;
}
@@ -262,41 +266,34 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
-void cChunk::SetAllData(
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const HeightMap * a_HeightMap,
- const BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities
-)
+void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
{
- memcpy(m_BiomeMap, a_BiomeMap, sizeof(m_BiomeMap));
+ ASSERT(a_SetChunkData.IsHeightMapValid());
+ ASSERT(a_SetChunkData.AreBiomesValid());
+
+ memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
+ memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
- if (a_HeightMap != NULL)
+ m_ChunkData.SetBlockTypes(a_SetChunkData.GetBlockTypes());
+ m_ChunkData.SetMetas(a_SetChunkData.GetBlockMetas());
+ if (a_SetChunkData.IsLightValid())
{
- memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
+ m_ChunkData.SetBlockLight(a_SetChunkData.GetBlockLight());
+ m_ChunkData.SetSkyLight(a_SetChunkData.GetSkyLight());
+ m_IsLightValid = true;
}
-
- if (a_HeightMap == NULL)
+ else
{
- CalculateHeightmap(a_BlockTypes);
+ m_IsLightValid = false;
}
- m_ChunkData.SetBlockTypes(a_BlockTypes);
- m_ChunkData.SetMetas(a_BlockMeta);
- m_ChunkData.SetBlockLight(a_BlockLight);
- m_ChunkData.SetSkyLight(a_BlockSkyLight);
-
- m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
-
// Clear the block entities present - either the loader / saver has better, or we'll create empty ones:
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
delete *itr;
}
- std::swap(a_BlockEntities, m_BlockEntities);
+ m_BlockEntities.clear();
+ std::swap(a_SetChunkData.GetBlockEntities(), m_BlockEntities);
// Set all block entities' World variable:
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
@@ -440,19 +437,19 @@ void cChunk::CollectMobCensus(cMobCensus& toFill)
{
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());
+ // 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());
+ toFill.CollectMob(Monster, *this, (currentPosition - **itr2).SqrLength());
}
}
} // for itr - m_Entitites[]
@@ -461,7 +458,7 @@ void cChunk::CollectMobCensus(cMobCensus& toFill)
-void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a_MaxY, int a_MaxZ)
+void cChunk::GetThreeRandomNumbers(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);
@@ -477,12 +474,12 @@ void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a
-void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
+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);
+ GetThreeRandomNumbers(a_X, a_Y, a_Z, Width, Height - 2, Width);
a_Y++;
}
@@ -492,65 +489,68 @@ void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
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);
-
- 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 : check that "Level" really means Y
-
- /*
- NIBBLETYPE SkyLight = 0;
-
- NIBBLETYPE BlockLight = 0;
- */
+ int CenterX, CenterY, CenterZ;
+ GetRandomBlockCoords(CenterX, CenterY, CenterZ);
- if (IsLightValid())
- {
- cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, MaxNbOfSuccess);
- if (newMob)
- {
- int WorldX, WorldY, WorldZ;
- PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ);
- double ActualX = WorldX + 0.5;
- double ActualZ = WorldZ + 0.5;
- newMob->SetPosition(ActualX, WorldY, ActualZ);
- LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ);
- NumberOfSuccess++;
- }
- }
-
- NumberOfTries++;
- }
+ BLOCKTYPE PackCenterBlock = GetBlock(CenterX, CenterY, CenterZ);
+ if (!a_MobSpawner.CheckPackCenter(PackCenterBlock))
+ {
+ return;
}
+
+ a_MobSpawner.NewPack();
+ int NumberOfTries = 0;
+ int NumberOfSuccess = 0;
+ int MaxNbOfSuccess = 4; // This can be changed during the process for Wolves and Ghasts
+ while ((NumberOfTries < 12) && (NumberOfSuccess < MaxNbOfSuccess))
+ {
+ const int HorizontalRange = 20; // MG TODO : relocate
+ const int VerticalRange = 0; // MG TODO : relocate
+ int TryX, TryY, TryZ;
+ GetThreeRandomNumbers(TryX, TryY, TryZ, 2 * HorizontalRange + 1, 2 * VerticalRange + 1, 2 * HorizontalRange + 1);
+ TryX -= HorizontalRange;
+ TryY -= VerticalRange;
+ TryZ -= HorizontalRange;
+ TryX += CenterX;
+ TryY += CenterY;
+ TryZ += CenterZ;
+
+ ASSERT(TryY > 0);
+ ASSERT(TryY < cChunkDef::Height - 1);
+
+ EMCSBiome Biome = m_ChunkMap->GetBiomeAt(TryX, TryZ);
+ // MG TODO :
+ // Moon cycle (for slime)
+ // check player and playerspawn presence < 24 blocks
+ // check mobs presence on the block
+
+ // MG TODO : check that "Level" really means Y
+
+ /*
+ NIBBLETYPE SkyLight = 0;
+ NIBBLETYPE BlockLight = 0;
+ */
+
+ NumberOfTries++;
+ if (!IsLightValid())
+ {
+ continue;
+ }
+
+ cEntity * newMob = a_MobSpawner.TryToSpawnHere(this, TryX, TryY, TryZ, Biome, MaxNbOfSuccess);
+ if (newMob == NULL)
+ {
+ continue;
+ }
+ int WorldX, WorldY, WorldZ;
+ PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
+ double ActualX = WorldX + 0.5;
+ double ActualZ = WorldZ + 0.5;
+ newMob->SetPosition(ActualX, WorldY, ActualZ);
+ LOGD("Spawning %s #%i at {%d, %d, %d}", newMob->GetClass(), newMob->GetUniqueID(), WorldX, WorldY, WorldZ);
+ NumberOfSuccess++;
+ } // while (retry)
}
@@ -577,38 +577,34 @@ void cChunk::Tick(float a_Dt)
m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty;
}
- // Tick all entities in this chunk (except mobs):
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
- {
- // Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players)
- if (!((*itr)->IsMob()))
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
+ {
+ if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
{
+ // Tick all entities in this chunk (except mobs):
(*itr)->Tick(a_Dt, *this);
}
- } // for itr - m_Entitites[]
-
- // Remove all entities that were scheduled for removal:
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
- {
- if ((*itr)->IsDestroyed())
- {
- LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
- cEntity * ToDelete = *itr;
- itr = m_Entities.erase(itr);
- delete ToDelete;
- continue;
- }
- ++itr;
- } // for itr - m_Entitites[]
-
- // If any entity moved out of the chunk, move it to the neighbor:
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
- {
- if (
+
+ if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
+ {
+ LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
+ MarkDirty();
+ cEntity * ToDelete = *itr;
+ itr = m_Entities.erase(itr);
+ delete ToDelete;
+ }
+ else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world:
+ {
+ MarkDirty();
+ (*itr)->SetWorldTravellingFrom(NULL);
+ itr = m_Entities.erase(itr);
+ }
+ else if ( // If any entity moved out of the chunk, move it to the neighbor:
((*itr)->GetChunkX() != m_PosX) ||
((*itr)->GetChunkZ() != m_PosZ)
)
{
+ MarkDirty();
MoveEntityToNewChunk(*itr);
itr = m_Entities.erase(itr);
}
@@ -616,7 +612,7 @@ void cChunk::Tick(float a_Dt)
{
++itr;
}
- }
+ } // for itr - m_Entitites[]
ApplyWeatherToTop();
}
@@ -631,7 +627,7 @@ void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
- Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface,*this, a_RelX, a_RelY, a_RelZ);
+ Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, a_RelX, a_RelY, a_RelZ);
}
@@ -691,13 +687,13 @@ void cChunk::ProcessQueuedSetBlocks(void)
{
if (itr->m_Tick <= CurrTick)
{
- if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to 0 if not specified
+ if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to 0 if not specified
{
if (GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ) == itr->m_PreviousType)
{
// Current world age is bigger than/equal to target world age - delay time reached AND
// Previous block type was the same as current block type (to prevent duplication)
- SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta); // SetMeta doesn't send to client
+ SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta); // SetMeta doesn't send to client
itr = m_SetBlockQueue.erase(itr);
LOGD("Successfully set queued block - previous and current types matched");
}
@@ -774,7 +770,7 @@ void cChunk::CheckBlocks()
void cChunk::TickBlocks(void)
{
// Tick dem blocks
- // _X: We must limit the random number or else we get a nasty int overflow bug ( http://forum.mc-server.org/showthread.php?tid=457 )
+ // _X: We must limit the random number or else we get a nasty int overflow bug - http://forum.mc-server.org/showthread.php?tid=457
int RandomX = m_World->GetTickRandomNumber(0x00ffffff);
int RandomY = m_World->GetTickRandomNumber(0x00ffffff);
int RandomZ = m_World->GetTickRandomNumber(0x00ffffff);
@@ -803,7 +799,7 @@ void cChunk::TickBlocks(void)
if (m_BlockTickY > cChunkDef::GetHeight(m_HeightMap, m_BlockTickX, m_BlockTickZ))
{
- continue; // It's all air up here
+ continue; // It's all air up here
}
cBlockHandler * Handler = BlockHandler(GetBlock(m_BlockTickX, m_BlockTickY, m_BlockTickZ));
@@ -888,7 +884,7 @@ void cChunk::ApplyWeatherToTop()
SetBlock(X, Height, Z, E_BLOCK_ICE, 0);
}
else if (
- (m_World->IsDeepSnowEnabled()) &&
+ (m_World->IsDeepSnowEnabled()) &&
(
(TopBlock == E_BLOCK_RED_ROSE) ||
(TopBlock == E_BLOCK_YELLOW_FLOWER) ||
@@ -901,7 +897,6 @@ void cChunk::ApplyWeatherToTop()
}
break;
} // case (snowy biomes)
- // TODO: Rainy biomes should check for farmland and cauldrons
default:
{
break;
@@ -937,10 +932,10 @@ void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
IsValid = IsValid && UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + 1, BlockType[2], BlockMeta);
IsValid = IsValid && UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ - 1, BlockType[3], BlockMeta);
if (
- !IsValid ||
- (BlockType[0] == ProduceType) ||
- (BlockType[1] == ProduceType) ||
- (BlockType[2] == ProduceType) ||
+ !IsValid ||
+ (BlockType[0] == ProduceType) ||
+ (BlockType[1] == ProduceType) ||
+ (BlockType[2] == ProduceType) ||
(BlockType[3] == ProduceType)
)
{
@@ -1222,7 +1217,7 @@ bool cChunk::UnboundedRelSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
}
Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
return true;
-}
+}
@@ -1294,6 +1289,7 @@ void cChunk::CreateBlockEntities(void)
switch (BlockType)
{
case E_BLOCK_BEACON:
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DISPENSER:
@@ -1386,7 +1382,7 @@ void cChunk::CalculateHeightmap(const BLOCKTYPE * a_BlockTypes)
{
for (int y = Height - 1; y > -1; y--)
{
- int index = MakeIndex( x, y, z );
+ int index = MakeIndex( x, y, z);
if (a_BlockTypes[index] != E_BLOCK_AIR)
{
m_HeightMap[x + z * Width] = (HEIGHTTYPE)y;
@@ -1417,12 +1413,14 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
BlockEntity->Destroy();
RemoveBlockEntity(BlockEntity);
delete BlockEntity;
+ BlockEntity = NULL;
}
// If the new block is a block entity, create the entity object:
switch (a_BlockType)
{
case E_BLOCK_BEACON:
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DISPENSER:
@@ -1520,11 +1518,12 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
m_ChunkData.SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType);
- if ( // Queue block to be sent only if ...
- a_SendToClients && // ... we are told to do so AND ...
+ // Queue block to be sent only if ...
+ if (
+ a_SendToClients && // ... we are told to do so AND ...
(
- (OldBlockMeta != a_BlockMeta) || // ... the meta value is different OR ...
- !( // ... the old and new blocktypes AREN'T liquids (because client doesn't need to distinguish betwixt them); see below for specifics:
+ (OldBlockMeta != a_BlockMeta) || // ... the meta value is different OR ...
+ !( // ... the old and new blocktypes AREN'T liquids (because client doesn't need to distinguish betwixt them):
((OldBlockType == E_BLOCK_STATIONARY_WATER) && (a_BlockType == E_BLOCK_WATER)) || // Replacing stationary water with water
((OldBlockType == E_BLOCK_WATER) && (a_BlockType == E_BLOCK_STATIONARY_WATER)) || // Replacing water with stationary water
((OldBlockType == E_BLOCK_STATIONARY_LAVA) && (a_BlockType == E_BLOCK_LAVA)) || // Replacing stationary water with water
@@ -1612,6 +1611,12 @@ void cChunk::AddBlockEntity(cBlockEntity * a_BlockEntity)
cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ)
{
+ // Check that the query coords are within chunk bounds:
+ ASSERT(a_BlockX >= m_PosX * cChunkDef::Width);
+ ASSERT(a_BlockX < m_PosX * cChunkDef::Width + cChunkDef::Width);
+ ASSERT(a_BlockZ >= m_PosZ * cChunkDef::Width);
+ ASSERT(a_BlockZ < m_PosZ * cChunkDef::Width + cChunkDef::Width);
+
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
if (
@@ -1631,6 +1636,31 @@ cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ)
+bool cChunk::ShouldBeTicked(void) const
+{
+ return (HasAnyClients() || (m_AlwaysTicked > 0));
+}
+
+
+
+
+
+void cChunk::SetAlwaysTicked(bool a_AlwaysTicked)
+{
+ if (a_AlwaysTicked)
+ {
+ m_AlwaysTicked += 1;
+ }
+ else
+ {
+ m_AlwaysTicked -= 1;
+ }
+}
+
+
+
+
+
void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z)
{
cBlockEntity * be = GetBlockEntity(a_X, a_Y, a_Z);
@@ -1686,11 +1716,11 @@ void cChunk::CollectPickupsByPlayer(cPlayer * a_Player)
{
if ((!(*itr)->IsPickup()) && (!(*itr)->IsProjectile()))
{
- continue; // Only pickups and projectiles
+ continue; // Only pickups and projectiles can be picked up
}
- float DiffX = (float)((*itr)->GetPosX() - PosX );
- float DiffY = (float)((*itr)->GetPosY() - PosY );
- float DiffZ = (float)((*itr)->GetPosZ() - PosZ );
+ float DiffX = (float)((*itr)->GetPosX() - PosX);
+ float DiffY = (float)((*itr)->GetPosY() - PosY);
+ float DiffZ = (float)((*itr)->GetPosZ() - PosZ);
float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ;
if (SqrDist < 1.5f * 1.5f) // 1.5 block
{
@@ -1752,7 +1782,7 @@ bool cChunk::SetSignLines(int a_PosX, int a_PosY, int a_PosZ, const AString & a_
-void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity )
+void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity)
{
MarkDirty();
m_BlockEntities.remove(a_BlockEntity);
@@ -1762,7 +1792,7 @@ void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity )
-bool cChunk::AddClient(cClientHandle* a_Client)
+bool cChunk::AddClient(cClientHandle * a_Client)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -1772,9 +1802,9 @@ bool cChunk::AddClient(cClientHandle* a_Client)
return false;
}
}
- m_LoadedByClient.push_back( a_Client );
+ m_LoadedByClient.push_back( a_Client);
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
/*
// DEBUG:
@@ -1793,7 +1823,7 @@ bool cChunk::AddClient(cClientHandle* a_Client)
-void cChunk::RemoveClient( cClientHandle* a_Client )
+void cChunk::RemoveClient(cClientHandle * a_Client)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -1801,12 +1831,12 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
{
continue;
}
-
+
m_LoadedByClient.erase(itr);
if (!a_Client->IsDestroyed())
{
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
/*
// DEBUG:
@@ -1826,7 +1856,7 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
-bool cChunk::HasClient( cClientHandle* a_Client )
+bool cChunk::HasClient(cClientHandle * a_Client)
{
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -1842,7 +1872,7 @@ bool cChunk::HasClient( cClientHandle* a_Client )
-bool cChunk::HasAnyClients(void)
+bool cChunk::HasAnyClients(void) const
{
return !m_LoadedByClient.empty();
}
@@ -1857,9 +1887,9 @@ void cChunk::AddEntity(cEntity * a_Entity)
{
MarkDirty();
}
-
+
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already
-
+
m_Entities.push_back(a_Entity);
}
@@ -1869,17 +1899,12 @@ void cChunk::AddEntity(cEntity * a_Entity)
void cChunk::RemoveEntity(cEntity * a_Entity)
{
- size_t SizeBefore = m_Entities.size();
m_Entities.remove(a_Entity);
- size_t SizeAfter = m_Entities.size();
-
- if (SizeBefore != SizeAfter)
+
+ // Mark as dirty if it was a server-generated entity:
+ if (!a_Entity->IsPlayer())
{
- // Mark as dirty if it was a server-generated entity:
- if (!a_Entity->IsPlayer())
- {
- MarkDirty();
- }
+ MarkDirty();
}
}
@@ -2111,7 +2136,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
{
continue;
}
- if ((*itr)->GetBlockType() != E_BLOCK_CHEST)
+ if (((*itr)->GetBlockType() != E_BLOCK_CHEST) && ((*itr)->GetBlockType() != E_BLOCK_TRAPPED_CHEST)) // Trapped chests use normal chests' handlers
{
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
return false;
@@ -2253,7 +2278,7 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
}
} // switch (BlockType)
- // The correct block entity is here,
+ // The correct block entity is here,
if (a_Callback.Item((cFurnaceEntity *)*itr))
{
return false;
@@ -2285,7 +2310,7 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here
if (a_Callback.Item((cNoteEntity *)*itr))
{
return false;
@@ -2317,7 +2342,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here,
if (a_Callback.Item((cCommandBlockEntity *)*itr))
{
return false;
@@ -2349,7 +2374,7 @@ bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadC
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here,
if (a_Callback.Item((cMobHeadEntity *)*itr))
{
return false;
@@ -2381,7 +2406,7 @@ bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlower
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here
if (a_Callback.Item((cFlowerPotEntity *)*itr))
{
return false;
@@ -2434,13 +2459,13 @@ bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_
BLOCKTYPE cChunk::GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
{
if (
- (a_RelX < 0) || (a_RelX >= Width) ||
+ (a_RelX < 0) || (a_RelX >= Width) ||
(a_RelY < 0) || (a_RelY >= Height) ||
(a_RelZ < 0) || (a_RelZ >= Width)
)
{
ASSERT(!"GetBlock(x, y, z) out of bounds!");
- return 0; // Clip
+ return 0; // Clip
}
return m_ChunkData.GetBlock(a_RelX, a_RelY, a_RelZ);
@@ -2491,8 +2516,8 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
{
int BlockX = m_PosX * cChunkDef::Width + a_RelX;
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
- int BlockY, ChunkX, ChunkZ;
- AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
+ int ChunkX, ChunkZ;
+ BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
}
@@ -2611,7 +2636,7 @@ cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) con
void cChunk::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
(*itr)->SendAttachEntity(a_Entity, a_Vehicle);
} // for itr - LoadedByClient[]
@@ -2623,7 +2648,7 @@ void cChunk::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_V
void cChunk::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2639,7 +2664,7 @@ void cChunk::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char
void cChunk::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2661,7 +2686,7 @@ void cChunk::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cons
{
return;
}
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2677,7 +2702,7 @@ void cChunk::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cons
void cChunk::BroadcastChunkData(cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2691,15 +2716,15 @@ void cChunk::BroadcastChunkData(cChunkDataSerializer & a_Serializer, const cClie
-void cChunk::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude)
+void cChunk::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
continue;
}
- (*itr)->SendCollectPickup(a_Pickup, a_Player);
+ (*itr)->SendCollectEntity(a_Entity, a_Player);
} // for itr - LoadedByClient[]
}
@@ -2709,7 +2734,7 @@ void cChunk::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_
void cChunk::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2725,7 +2750,7 @@ void cChunk::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandl
void cChunk::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2741,7 +2766,7 @@ void cChunk::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int
void cChunk::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2757,7 +2782,7 @@ void cChunk::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum,
void cChunk::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2773,7 +2798,7 @@ void cChunk::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHand
void cChunk::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2789,7 +2814,7 @@ void cChunk::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle *
void cChunk::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2805,7 +2830,7 @@ void cChunk::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHand
void cChunk::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2821,7 +2846,7 @@ void cChunk::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char
void cChunk::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2837,7 +2862,7 @@ void cChunk::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, c
void cChunk::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2853,7 +2878,7 @@ void cChunk::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, cons
void cChunk::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2869,7 +2894,7 @@ void cChunk::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHand
void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2885,7 +2910,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)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2901,7 +2926,7 @@ void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src
void cChunk::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2915,15 +2940,15 @@ void cChunk::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectI
-void cChunk::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
+void cChunk::BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
continue;
}
- (*itr)->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);
+ (*itr)->SendSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch);
} // for itr - LoadedByClient[]
}
@@ -2933,7 +2958,7 @@ void cChunk::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a
void cChunk::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2949,7 +2974,7 @@ void cChunk::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY
void cChunk::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2965,7 +2990,7 @@ void cChunk::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Ex
void cChunk::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2979,9 +3004,9 @@ void cChunk::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
-void cChunk::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ )
+void cChunk::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
(*itr)->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ);
} // for itr - LoadedByClient[]