summaryrefslogtreecommitdiffstats
path: root/src/Chunk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Chunk.cpp')
-rw-r--r--src/Chunk.cpp659
1 files changed, 183 insertions, 476 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index c196c3fe5..9516559ce 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -15,6 +15,7 @@
#include "BlockEntities/BeaconEntity.h"
#include "BlockEntities/BrewingstandEntity.h"
#include "BlockEntities/ChestEntity.h"
+#include "BlockEntities/CommandBlockEntity.h"
#include "BlockEntities/DispenserEntity.h"
#include "BlockEntities/DropperEntity.h"
#include "BlockEntities/FlowerPotEntity.h"
@@ -125,22 +126,22 @@ cChunk::~cChunk()
// 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)
+ for (auto & KeyPair : m_BlockEntities)
{
- delete *itr;
+ delete KeyPair.second;
}
m_BlockEntities.clear();
// Remove and destroy all entities that are not players:
cEntityList Entities;
std::swap(Entities, m_Entities); // Need another list because cEntity destructors check if they've been removed from chunk
- for (cEntityList::const_iterator itr = Entities.begin(); itr != Entities.end(); ++itr)
+ for (auto Entity : Entities)
{
- if (!(*itr)->IsPlayer())
+ if (!Entity->IsPlayer())
{
// Scheduling a normal destruction is neither possible (Since this chunk will be gone till the schedule occurs) nor necessary.
- (*itr)->DestroyNoScheduling(false); // No point in broadcasting in an unloading chunk. Chunks unload when no one is nearby.
- delete *itr;
+ Entity->DestroyNoScheduling(false); // No point in broadcasting in an unloading chunk. Chunks unload when no one is nearby.
+ delete Entity;
}
}
@@ -298,14 +299,14 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
a_Callback.ChunkData(m_ChunkData);
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
+ for (auto Entity : m_Entities)
{
- a_Callback.Entity(*itr);
+ a_Callback.Entity(Entity);
}
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
+ for (auto & KeyPair : m_BlockEntities)
{
- a_Callback.BlockEntity(*itr);
+ a_Callback.BlockEntity(KeyPair.second);
}
}
@@ -335,27 +336,28 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
}
// 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)
+ for (auto & KeyPair : m_BlockEntities)
{
- delete *itr;
+ delete KeyPair.second;
}
m_BlockEntities.clear();
std::swap(a_SetChunkData.GetBlockEntities(), m_BlockEntities);
// Check that all block entities have a valid blocktype at their respective coords (DEBUG-mode only):
#ifdef _DEBUG
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
+ for (auto & KeyPair : m_BlockEntities)
{
- BLOCKTYPE EntityBlockType = (*itr)->GetBlockType();
- BLOCKTYPE WorldBlockType = GetBlock((*itr)->GetRelX(), (*itr)->GetPosY(), (*itr)->GetRelZ());
+ cBlockEntity * Block = KeyPair.second;
+ BLOCKTYPE EntityBlockType = Block->GetBlockType();
+ BLOCKTYPE WorldBlockType = GetBlock(Block->GetRelX(), Block->GetPosY(), Block->GetRelZ());
ASSERT(WorldBlockType == EntityBlockType);
- } // for itr - m_BlockEntities
+ } // for KeyPair - m_BlockEntities
#endif // _DEBUG
// Set all block entities' World variable:
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
+ for (auto & KeyPair : m_BlockEntities)
{
- (*itr)->SetWorld(m_World);
+ KeyPair.second->SetWorld(m_World);
}
// Create block entities that the loader didn't load; fill them with defaults
@@ -457,18 +459,7 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
bool cChunk::HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ)
{
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
- {
- if (
- ((*itr)->GetPosX() == a_BlockX) &&
- ((*itr)->GetPosY() == a_BlockY) &&
- ((*itr)->GetPosZ() == a_BlockZ)
- )
- {
- return true;
- }
- } // for itr - m_BlockEntities[]
- return false;
+ return (GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ) != nullptr);
}
@@ -638,9 +629,9 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
TickBlocks();
// Tick all block entities in this chunk:
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
+ for (auto & KeyPair : m_BlockEntities)
{
- m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty;
+ m_IsDirty = KeyPair.second->Tick(a_Dt, *this) | m_IsDirty;
}
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
@@ -1382,7 +1373,7 @@ void cChunk::CreateBlockEntities(void)
{
if (!HasBlockEntityAt(x + m_PosX * Width, y, z + m_PosZ * Width))
{
- m_BlockEntities.push_back(cBlockEntity::CreateByBlockType(
+ AddBlockEntityClean(cBlockEntity::CreateByBlockType(
BlockType, GetMeta(x, y, z),
x + m_PosX * Width, y, z + m_PosZ * Width, m_World
));
@@ -1513,7 +1504,8 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
case E_BLOCK_MOB_SPAWNER:
case E_BLOCK_BREWING_STAND:
{
- AddBlockEntity(cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, WorldPos.x, WorldPos.y, WorldPos.z, m_World));
+ // Fast set block has already marked dirty
+ AddBlockEntityClean(cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, WorldPos.x, WorldPos.y, WorldPos.z, m_World));
break;
}
} // switch (a_BlockType)
@@ -1663,13 +1655,11 @@ void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_C
a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ));
// FS #268 - if a BlockEntity digging is cancelled by a plugin, the entire block entity must be re-sent to the client:
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), end = m_BlockEntities.end(); itr != end; ++itr)
+ cBlockEntity * Block = GetBlockEntity(wp.x, wp.y, wp.z);
+ if (Block != nullptr)
{
- if (((*itr)->GetPosX() == wp.x) && ((*itr)->GetPosY() == wp.y) && ((*itr)->GetPosZ() == wp.z))
- {
- (*itr)->SendTo(*a_Client);
- }
- } // for itr - m_BlockEntities
+ Block->SendTo(*a_Client);
+ }
}
@@ -1679,7 +1669,19 @@ void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_C
void cChunk::AddBlockEntity(cBlockEntity * a_BlockEntity)
{
MarkDirty();
- m_BlockEntities.push_back(a_BlockEntity);
+ AddBlockEntityClean(a_BlockEntity);
+}
+
+
+
+
+
+void cChunk::AddBlockEntityClean(cBlockEntity * a_BlockEntity)
+{
+ int Idx = MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ());
+ auto Result = m_BlockEntities.insert({ Idx, a_BlockEntity });
+ UNUSED(Result);
+ ASSERT(Result.second); // No block entity already at this position
}
@@ -1694,19 +1696,11 @@ cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ)
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 (
- ((*itr)->GetPosX() == a_BlockX) &&
- ((*itr)->GetPosY() == a_BlockY) &&
- ((*itr)->GetPosZ() == a_BlockZ)
- )
- {
- return *itr;
- }
- } // for itr - m_BlockEntities[]
+ int RelX = a_BlockX - m_PosX * cChunkDef::Width;
+ int RelZ = a_BlockZ - m_PosZ * cChunkDef::Width;
- return nullptr;
+ auto itr = m_BlockEntities.find(MakeIndex(RelX, a_BlockY, RelZ));
+ return (itr == m_BlockEntities.end()) ? nullptr : itr->second;
}
@@ -1837,25 +1831,24 @@ void cChunk::CollectPickupsByPlayer(cPlayer & a_Player)
bool cChunk::SetSignLines(int a_PosX, int a_PosY, int a_PosZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
{
// Also sends update packets to all clients in the chunk
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
+ auto Entity = GetBlockEntity(a_PosX, a_PosY, a_PosZ);
+ if (Entity == nullptr)
{
- if (
- ((*itr)->GetPosX() == a_PosX) &&
- ((*itr)->GetPosY() == a_PosY) &&
- ((*itr)->GetPosZ() == a_PosZ) &&
- (
- ((*itr)->GetBlockType() == E_BLOCK_WALLSIGN) ||
- ((*itr)->GetBlockType() == E_BLOCK_SIGN_POST)
- )
- )
- {
- MarkDirty();
- reinterpret_cast<cSignEntity *>(*itr)->SetLines(a_Line1, a_Line2, a_Line3, a_Line4);
- m_World->BroadcastBlockEntity(a_PosX, a_PosY, a_PosZ);
- return true;
- }
- } // for itr - m_BlockEntities[]
- return false;
+ return false; // Not a block entity
+ }
+ if (
+ (Entity->GetBlockType() != E_BLOCK_WALLSIGN) &&
+ (Entity->GetBlockType() != E_BLOCK_SIGN_POST)
+ )
+ {
+ return false; // Not a sign
+ }
+
+ MarkDirty();
+ auto Sign = static_cast<cSignEntity *>(Entity);
+ Sign->SetLines(a_Line1, a_Line2, a_Line3, a_Line4);
+ m_World->BroadcastBlockEntity(a_PosX, a_PosY, a_PosZ);
+ return true;
}
@@ -1865,7 +1858,9 @@ bool cChunk::SetSignLines(int a_PosX, int a_PosY, int a_PosZ, const AString & a_
void cChunk::RemoveBlockEntity(cBlockEntity * a_BlockEntity)
{
MarkDirty();
- m_BlockEntities.remove(a_BlockEntity);
+ ASSERT(a_BlockEntity != nullptr);
+ int Idx = MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ());
+ m_BlockEntities.erase(Idx);
}
@@ -2076,17 +2071,24 @@ bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cLambdaEntityCallback a_Callbac
-bool cChunk::ForEachBlockEntity(cBlockEntityCallback & a_Callback)
+template <class tyEntity, BLOCKTYPE... tBlocktype>
+bool cChunk::GenericForEachBlockEntity(cItemCallback<tyEntity>& a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
+ for (auto & KeyPair : m_BlockEntities)
{
- ++itr2;
- if (a_Callback.Item(*itr))
+ cBlockEntity * Block = KeyPair.second;
+ if (
+ (sizeof...(tBlocktype) == 0) || // Let empty list mean all block entities
+ (IsOneOf<tBlocktype...>(Block->GetBlockType()))
+ )
{
- return false;
+ if (a_Callback.Item(static_cast<tyEntity *>(Block)))
+ {
+ return false;
+ }
}
- } // for itr - m_BlockEntitites[]
+ } // for KeyPair - m_BlockEntitites[]
return true;
}
@@ -2094,18 +2096,20 @@ bool cChunk::ForEachBlockEntity(cBlockEntityCallback & a_Callback)
+bool cChunk::ForEachBlockEntity(cBlockEntityCallback & a_Callback)
+{
+ return GenericForEachBlockEntity<cBlockEntity>(a_Callback);
+}
+
+
+
+
+
bool cChunk::ForEachBrewingstand(cBrewingstandCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (a_Callback.Item(reinterpret_cast<cBrewingstandEntity *>(*itr)))
- {
- return false;
- }
- } // for itr - m_BlockEntitites[]
- return true;
+ return GenericForEachBlockEntity<cBrewingstandEntity,
+ E_BLOCK_BREWING_STAND
+ >(a_Callback);
}
@@ -2114,20 +2118,9 @@ bool cChunk::ForEachBrewingstand(cBrewingstandCallback & a_Callback)
bool cChunk::ForEachChest(cChestCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if ((*itr)->GetBlockType() != E_BLOCK_CHEST)
- {
- continue;
- }
- if (a_Callback.Item(reinterpret_cast<cChestEntity *>(*itr)))
- {
- return false;
- }
- } // for itr - m_BlockEntitites[]
- return true;
+ return GenericForEachBlockEntity<cChestEntity,
+ E_BLOCK_CHEST
+ >(a_Callback);
}
@@ -2136,20 +2129,9 @@ bool cChunk::ForEachChest(cChestCallback & a_Callback)
bool cChunk::ForEachDispenser(cDispenserCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if ((*itr)->GetBlockType() != E_BLOCK_DISPENSER)
- {
- continue;
- }
- if (a_Callback.Item(reinterpret_cast<cDispenserEntity *>(*itr)))
- {
- return false;
- }
- } // for itr - m_BlockEntitites[]
- return true;
+ return GenericForEachBlockEntity<cDispenserEntity,
+ E_BLOCK_DISPENSER
+ >(a_Callback);
}
@@ -2158,20 +2140,9 @@ bool cChunk::ForEachDispenser(cDispenserCallback & a_Callback)
bool cChunk::ForEachDropper(cDropperCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if ((*itr)->GetBlockType() != E_BLOCK_DROPPER)
- {
- continue;
- }
- if (a_Callback.Item(reinterpret_cast<cDropperEntity *>(*itr)))
- {
- return false;
- }
- } // for itr - m_BlockEntitites[]
- return true;
+ return GenericForEachBlockEntity<cDropperEntity,
+ E_BLOCK_DROPPER
+ >(a_Callback);
}
@@ -2180,20 +2151,10 @@ bool cChunk::ForEachDropper(cDropperCallback & a_Callback)
bool cChunk::ForEachDropSpenser(cDropSpenserCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetBlockType() != E_BLOCK_DISPENSER) && ((*itr)->GetBlockType() != E_BLOCK_DROPPER))
- {
- continue;
- }
- if (a_Callback.Item(reinterpret_cast<cDropSpenserEntity *>(*itr)))
- {
- return false;
- }
- } // for itr - m_BlockEntitites[]
- return true;
+ return GenericForEachBlockEntity<cDropSpenserEntity,
+ E_BLOCK_DISPENSER,
+ E_BLOCK_DROPPER
+ >(a_Callback);
}
@@ -2202,54 +2163,42 @@ bool cChunk::ForEachDropSpenser(cDropSpenserCallback & a_Callback)
bool cChunk::ForEachFurnace(cFurnaceCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- switch ((*itr)->GetBlockType())
- {
- case E_BLOCK_FURNACE:
- case E_BLOCK_LIT_FURNACE:
- {
- break;
- }
- default:
- {
- continue;
- }
- }
- if (a_Callback.Item(reinterpret_cast<cFurnaceEntity *>(*itr)))
- {
- return false;
- }
- } // for itr - m_BlockEntitites[]
- return true;
+ return GenericForEachBlockEntity<cFurnaceEntity,
+ E_BLOCK_FURNACE,
+ E_BLOCK_LIT_FURNACE
+ >(a_Callback);
}
-bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback)
+template <class tyEntity, BLOCKTYPE... tBlocktype>
+bool cChunk::GenericDoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cItemCallback<tyEntity>& a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
+ cBlockEntity * Block = GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ);
+ if (Block == nullptr)
{
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
+ return false; // No block entity here
+ }
+ if (
+ (sizeof...(tBlocktype) != 0) && // Let empty list mean all block entities
+ (!IsOneOf<tBlocktype...>(Block->GetBlockType()))
+ )
+ {
+ return false; // Not any of the given tBlocktypes
+ }
+ return !a_Callback.Item(static_cast<tyEntity *>(Block));
+}
- if (a_Callback.Item(*itr))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
- // Not found:
- return false;
+
+
+
+bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback)
+{
+ return GenericDoWithBlockEntityAt<cBlockEntity>(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2257,30 +2206,9 @@ bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBloc
bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_BEACON)
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cBeaconEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cBeaconEntity,
+ E_BLOCK_BEACON
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2289,30 +2217,9 @@ bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCal
bool cChunk::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_BREWING_STAND)
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cBrewingstandEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cBrewingstandEntity,
+ E_BLOCK_BREWING_STAND
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2321,30 +2228,10 @@ bool cChunk::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBre
bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cChestEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cChestEntity,
+ E_BLOCK_CHEST,
+ E_BLOCK_TRAPPED_CHEST
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2353,30 +2240,9 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_DISPENSER)
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cDispenserEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cDispenserEntity,
+ E_BLOCK_DISPENSER
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2385,30 +2251,9 @@ bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispen
bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_DROPPER)
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cDropperEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cDropperEntity,
+ E_BLOCK_DROPPER
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2417,30 +2262,10 @@ bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperC
bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if (((*itr)->GetBlockType() != E_BLOCK_DISPENSER) && ((*itr)->GetBlockType() != E_BLOCK_DROPPER))
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cDropSpenserEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cDropSpenserEntity,
+ E_BLOCK_DISPENSER,
+ E_BLOCK_DROPPER
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2449,38 +2274,10 @@ bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDrop
bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- switch ((*itr)->GetBlockType())
- {
- case E_BLOCK_FURNACE:
- case E_BLOCK_LIT_FURNACE:
- {
- break;
- }
- default:
- {
- // 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;
- }
- } // switch (BlockType)
-
- // The correct block entity is here,
- if (a_Callback.Item(reinterpret_cast<cFurnaceEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cFurnaceEntity,
+ E_BLOCK_FURNACE,
+ E_BLOCK_LIT_FURNACE
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2489,30 +2286,9 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_NOTE_BLOCK)
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cNoteEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cNoteEntity,
+ E_BLOCK_NOTE_BLOCK
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2521,30 +2297,9 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_COMMAND_BLOCK)
- {
- // 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;
- }
-
- // The correct block entity is here,
- if (a_Callback.Item(reinterpret_cast<cCommandBlockEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cCommandBlockEntity,
+ E_BLOCK_COMMAND_BLOCK
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2553,30 +2308,9 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom
bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_HEAD)
- {
- // 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;
- }
-
- // The correct block entity is here,
- if (a_Callback.Item(reinterpret_cast<cMobHeadEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cMobHeadEntity,
+ E_BLOCK_HEAD
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2585,30 +2319,9 @@ bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadC
bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback)
{
- // The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
- {
- ++itr2;
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- if ((*itr)->GetBlockType() != E_BLOCK_FLOWER_POT)
- {
- // 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;
- }
-
- // The correct block entity is here
- if (a_Callback.Item(reinterpret_cast<cFlowerPotEntity *>(*itr)))
- {
- return false;
- }
- return true;
- } // for itr - m_BlockEntitites[]
-
- // Not found:
- return false;
+ return GenericDoWithBlockEntityAt<cFlowerPotEntity,
+ E_BLOCK_FLOWER_POT
+ >(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
@@ -2618,31 +2331,25 @@ bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlower
bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
// The blockentity list is locked by the parent chunkmap's CS
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
+ auto Entity = GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ);
+ if (Entity == nullptr)
{
- if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
- {
- continue;
- }
- switch ((*itr)->GetBlockType())
- {
- case E_BLOCK_WALLSIGN:
- case E_BLOCK_SIGN_POST:
- {
- a_Line1 = reinterpret_cast<cSignEntity *>(*itr)->GetLine(0);
- a_Line2 = reinterpret_cast<cSignEntity *>(*itr)->GetLine(1);
- a_Line3 = reinterpret_cast<cSignEntity *>(*itr)->GetLine(2);
- a_Line4 = reinterpret_cast<cSignEntity *>(*itr)->GetLine(3);
- return true;
- }
- } // switch (BlockType)
-
- // 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;
- } // for itr - m_BlockEntitites[]
+ return false; // Not a block entity
+ }
+ if (
+ (Entity->GetBlockType() != E_BLOCK_WALLSIGN) &&
+ (Entity->GetBlockType() != E_BLOCK_SIGN_POST)
+ )
+ {
+ return false; // Not a sign
+ }
- // Not found:
- return false;
+ auto Sign = static_cast<cSignEntity *>(Entity);
+ a_Line1 = Sign->GetLine(0);
+ a_Line2 = Sign->GetLine(1);
+ a_Line3 = Sign->GetLine(2);
+ a_Line4 = Sign->GetLine(3);
+ return true;
}