summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2020-07-29 20:30:38 +0200
committerTiger Wang <ziwei.tiger@outlook.com>2020-08-04 19:15:18 +0200
commit6bdd130aab51b630918ed664c4389cf33bcb2e06 (patch)
treeeed35c8716f9ea18afe8fd909c09e8595928a671
parentDo not GetBlock individually in simulators (diff)
downloadcuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.tar
cuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.tar.gz
cuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.tar.bz2
cuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.tar.lz
cuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.tar.xz
cuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.tar.zst
cuberite-6bdd130aab51b630918ed664c4389cf33bcb2e06.zip
-rw-r--r--src/Blocks/BlockConcretePowder.h67
-rw-r--r--src/Blocks/BlockHandler.cpp64
-rw-r--r--src/Blocks/BlockHandler.h27
-rw-r--r--src/Blocks/BlockPlant.h2
-rw-r--r--src/Blocks/ChunkInterface.cpp21
-rw-r--r--src/Blocks/ChunkInterface.h4
-rw-r--r--src/Chunk.cpp33
-rw-r--r--src/Chunk.h4
-rw-r--r--src/ChunkMap.cpp58
-rw-r--r--src/ChunkMap.h8
-rw-r--r--src/ClientHandle.cpp1
-rw-r--r--src/Entities/Player.cpp14
-rw-r--r--src/Items/ItemChest.h2
-rw-r--r--src/Items/ItemLighter.h4
-rw-r--r--src/World.cpp29
-rw-r--r--src/World.h14
16 files changed, 92 insertions, 260 deletions
diff --git a/src/Blocks/BlockConcretePowder.h b/src/Blocks/BlockConcretePowder.h
index d3133a571..7cd99149e 100644
--- a/src/Blocks/BlockConcretePowder.h
+++ b/src/Blocks/BlockConcretePowder.h
@@ -19,66 +19,41 @@ public:
{
}
-
-
-
-
- virtual void Check(
- cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface,
- Vector3i a_RelPos,
- cChunk & a_Chunk
+ virtual void OnPlaced(
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
+ Vector3i a_BlockPos,
+ BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override
{
- if (GetSoaked(a_RelPos, a_Chunk))
- {
- return;
- }
- Super::Check(a_ChunkInterface, a_PluginInterface, a_RelPos, a_Chunk);
+ OnNeighborChanged(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NONE);
}
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
+ {
+ a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { CheckSoaked(a_Chunk.AbsoluteToRelative(a_BlockPos), a_Chunk); return true; });
+ }
-
-
-
- /** Check blocks above and around to see if they are water. If one is, converts this into concrete block.
- Returns true if the block was changed. */
- bool GetSoaked(Vector3i a_Rel, cChunk & a_Chunk)
+ /** Check blocks above and around to see if they are water. If one is, converts this into concrete block. */
+ void CheckSoaked(Vector3i a_Rel, cChunk & a_Chunk)
{
- static const std::array<Vector3i, 5> WaterCheck
+ const auto & WaterCheck = cSimulator::AdjacentOffsets;
+ const bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, & a_Chunk](Vector3i a_Offset)
{
- {
- { 1, 0, 0},
- {-1, 0, 0},
- { 0, 0, 1},
- { 0, 0, -1},
- { 0, 1, 0},
- }
- };
-
- bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, & a_Chunk](Vector3i a_Offset)
- {
- BLOCKTYPE NeighborType;
- return (
- a_Chunk.UnboundedRelGetBlockType(a_Rel.x + a_Offset.x, a_Rel.y + a_Offset.y, a_Rel.z + a_Offset.z, NeighborType)
- && IsBlockWater(NeighborType)
- );
- }
- );
+ BLOCKTYPE NeighborType;
+ return (
+ a_Chunk.UnboundedRelGetBlockType(a_Rel.x + a_Offset.x, a_Rel.y + a_Offset.y, a_Rel.z + a_Offset.z, NeighborType)
+ && IsBlockWater(NeighborType)
+ );
+ });
if (ShouldSoak)
{
NIBBLETYPE BlockMeta;
BlockMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z);
a_Chunk.SetBlock(a_Rel, E_BLOCK_CONCRETE, BlockMeta);
- return true;
}
- return false;
}
-
-
-
-
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
{
switch (a_Meta)
@@ -107,7 +82,3 @@ public:
}
}
};
-
-
-
-
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index b7e746418..c3535987c 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -436,39 +436,21 @@ void cBlockHandler::OnUpdate(
-void cBlockHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange)
+void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor)
{
- OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockChange.GetAbsolutePos(), a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta);
-}
-
-
-
-
-
-void cBlockHandler::OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
-{
- // Notify the neighbors
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedX(-1), BLOCK_FACE_XP);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedX( 1), BLOCK_FACE_XM);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedY(-1), BLOCK_FACE_YP);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedY( 1), BLOCK_FACE_YM);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedZ(-1), BLOCK_FACE_ZP);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedZ( 1), BLOCK_FACE_ZM);
-}
-
-
-
-
+ if (a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { return CanBeAt(a_ChunkInterface, a_Chunk.AbsoluteToRelative(a_BlockPos), a_Chunk); }))
+ {
+ return;
+ }
-void cBlockHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta)
-{
- // Notify the neighbors
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedX(-1), BLOCK_FACE_XP);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedX( 1), BLOCK_FACE_XM);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedY(-1), BLOCK_FACE_YP);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedY( 1), BLOCK_FACE_YM);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedZ(-1), BLOCK_FACE_ZP);
- NeighborChanged(a_ChunkInterface, a_BlockPos.addedZ( 1), BLOCK_FACE_ZM);
+ if (DoesDropOnUnsuitable())
+ {
+ a_ChunkInterface.DropBlockAsPickups(a_BlockPos);
+ }
+ else
+ {
+ a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_AIR, 0);
+ }
}
@@ -585,19 +567,13 @@ void cBlockHandler::Check(
cChunk & a_Chunk
)
{
- if (CanBeAt(a_ChunkInterface, a_RelPos, a_Chunk))
- {
- return;
- }
-
- if (DoesDropOnUnsuitable())
- {
- a_ChunkInterface.DropBlockAsPickups(a_Chunk.RelativeToAbsolute(a_RelPos));
- }
- else
- {
- a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0);
- }
+ const auto Position = cChunkDef::RelativeToAbsolute(a_RelPos, a_Chunk.GetPos());
+ NeighborChanged(a_ChunkInterface, Position.addedX(-1), BLOCK_FACE_XP);
+ NeighborChanged(a_ChunkInterface, Position.addedX(1), BLOCK_FACE_XM);
+ NeighborChanged(a_ChunkInterface, Position.addedY(-1), BLOCK_FACE_YP);
+ NeighborChanged(a_ChunkInterface, Position.addedY(1), BLOCK_FACE_YM);
+ NeighborChanged(a_ChunkInterface, Position.addedZ(-1), BLOCK_FACE_ZP);
+ NeighborChanged(a_ChunkInterface, Position.addedZ(1), BLOCK_FACE_ZM);
}
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index a582b8dc2..90866fbb7 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -65,21 +65,12 @@ public:
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
- );
+ ) {};
/** Called by cPlayer::PlaceBlocks() for each block after it has been set to the world. Called after OnPlaced(). */
virtual void OnPlacedByPlayer(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange
- );
-
- /** Called just before the player breaks the block.
- The block is still valid in the world.
- By default does nothing special; descendants may provide further behavior. */
- virtual void OnPlayerBreakingBlock(
- cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
- cPlayer & a_Player,
- Vector3i a_BlockPos
- ) {}
+ ) {};
/** Called just after the player breaks the block.
The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta.
@@ -91,14 +82,6 @@ public:
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
) {}
- /** Called before a block gets broken (replaced with air), either by player or by natural means.
- If by player, it is called after the OnPlayerBreakingBlock() callback.
- By default does nothing. */
- virtual void OnBreaking(
- cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
- Vector3i a_BlockPos
- ) {}
-
/** Called after a block gets broken (replaced with air), either by player or by natural means.
If by player, it is called before the OnPlayerBrokeBlock() callback.
The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta.
@@ -107,13 +90,13 @@ public:
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
- );
+ ) {};
/** Called when a direct neighbor of this block has been changed.
The position is the block's own position, NOT the changed neighbor's position.
a_WhichNeighbor indicates which neighbor has changed. For example, BLOCK_FACE_YP meant the neighbor above has changed.
BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */
- virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) {}
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor);
/** Notifies the specified neighbor that the current block has changed.
a_NeighborPos are the coords of the neighbor to be notified
@@ -208,7 +191,7 @@ public:
/** Called when one of the neighbors gets set; equivalent to MC block update.
By default drops (DropBlockAsPickup() / SetBlock()) if the position is no longer suitable (CanBeAt(), DoesDropOnUnsuitable()),
otherwise wakes up all simulators on the block. */
- virtual void Check(
+ void Check(
cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface,
Vector3i a_RelPos,
cChunk & a_Chunk
diff --git a/src/Blocks/BlockPlant.h b/src/Blocks/BlockPlant.h
index b0760528c..a0d6ffe52 100644
--- a/src/Blocks/BlockPlant.h
+++ b/src/Blocks/BlockPlant.h
@@ -44,7 +44,7 @@ public:
}
case paDeath:
{
- a_ChunkInterface.DigBlock(a_WorldInterface, a_Chunk.RelativeToAbsolute(a_RelPos));
+ a_ChunkInterface.SetBlock(a_Chunk.RelativeToAbsolute(a_RelPos), E_BLOCK_AIR, 0);
break;
}
case paStay: break; // do nothing
diff --git a/src/Blocks/ChunkInterface.cpp b/src/Blocks/ChunkInterface.cpp
index fd64ee9fc..15198dd37 100644
--- a/src/Blocks/ChunkInterface.cpp
+++ b/src/Blocks/ChunkInterface.cpp
@@ -12,6 +12,15 @@
+bool cChunkInterface::DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback)
+{
+ return m_ChunkMap->DoWithChunkAt(a_BlockPos, a_Callback);
+}
+
+
+
+
+
BLOCKTYPE cChunkInterface::GetBlock(Vector3i a_Pos)
{
return m_ChunkMap->GetBlock(a_Pos);
@@ -95,16 +104,16 @@ bool cChunkInterface::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a
bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos)
{
- BLOCKTYPE blockType;
- NIBBLETYPE blockMeta;
- GetBlockTypeMeta(a_BlockPos, blockType, blockMeta);
- auto handler = cBlockInfo::GetHandler(blockType);
- handler->OnBreaking(*this, a_WorldInterface, a_BlockPos);
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
+
if (!m_ChunkMap->DigBlock(a_BlockPos))
{
return false;
}
- handler->OnBroken(*this, a_WorldInterface, a_BlockPos, blockType, blockMeta);
+
+ cBlockInfo::GetHandler(BlockType)->OnBroken(*this, a_WorldInterface, a_BlockPos, BlockType, BlockMeta);
return true;
}
diff --git a/src/Blocks/ChunkInterface.h b/src/Blocks/ChunkInterface.h
index 345fca4d2..6ee54b17f 100644
--- a/src/Blocks/ChunkInterface.h
+++ b/src/Blocks/ChunkInterface.h
@@ -2,12 +2,14 @@
#pragma once
#include "../ForEachChunkProvider.h"
+#include "../FunctionRef.h"
// fwd:
class cItem;
+class cChunk;
class cChunkMap;
class cWorldInterface;
class cPlayer;
@@ -23,6 +25,8 @@ public:
cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {}
+ bool DoWithChunkAt(Vector3i a_BlockPos, cFunctionRef<bool(cChunk &)> a_Callback);
+
BLOCKTYPE GetBlock(Vector3i a_Pos);
NIBBLETYPE GetBlockMeta(Vector3i a_Pos);
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 2140bf7f1..21261e828 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -820,7 +820,7 @@ void cChunk::CheckBlocks()
while (Count != 0)
{
- Vector3i Pos = m_ToTickBlocks.front();
+ const auto Pos = m_ToTickBlocks.front();
m_ToTickBlocks.pop();
Count--;
@@ -1263,8 +1263,8 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
{
FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta);
- // Tick this block and its neighbors:
- QueueTickBlockNeighbors(a_RelPos);
+ // Tick this block's neighbors via cBlockHandler::Check:
+ m_ToTickBlocks.push(a_RelPos);
// Wake up the simulators for this block:
GetWorld()->GetSimulatorManager()->WakeUp(*this, a_RelPos);
@@ -1311,33 +1311,6 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
-void cChunk::QueueTickBlockNeighbors(Vector3i a_Position)
-{
- m_ToTickBlocks.push(a_Position);
-
- for (const auto & Offset : cSimulator::AdjacentOffsets)
- {
- auto Relative = a_Position + Offset;
-
- if (!cChunkDef::IsValidHeight(Relative.y))
- {
- continue;
- }
-
- auto Chunk = GetRelNeighborChunkAdjustCoords(Relative);
- if ((Chunk == nullptr) || !Chunk->IsValid())
- {
- continue;
- }
-
- Chunk->m_ToTickBlocks.push(Relative);
- }
-}
-
-
-
-
-
void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients)
{
ASSERT(!((a_RelX < 0) || (a_RelX >= Width) || (a_RelY < 0) || (a_RelY >= Height) || (a_RelZ < 0) || (a_RelZ >= Width)));
diff --git a/src/Chunk.h b/src/Chunk.h
index 7e09ce8b6..d88b16555 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -158,10 +158,6 @@ public:
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
- /** Queues the position itself, and all 6 neighbors of the specified position for ticking (m_ToTickQueue).
- If any are outside the chunk, relays the checking to the proper neighboring chunk. */
- void QueueTickBlockNeighbors(Vector3i a_Position);
-
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients = true); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
void FastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients = true)
{
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 9b5106f36..6ec3da404 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -479,34 +479,6 @@ void cChunkMap::FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLET
-void cChunkMap::SetBlocks(const sSetBlockVector & a_Blocks)
-{
- cCSLock lock(m_CSChunks);
- cChunkPtr chunk = nullptr;
- int lastChunkX = 0x7fffffff; // Bogus coords so that chunk is updated on first pass
- int lastChunkZ = 0x7fffffff;
- for (auto block: a_Blocks)
- {
- // Update the chunk, if different from last time:
- if ((block.m_ChunkX != lastChunkX) || (block.m_ChunkZ != lastChunkZ))
- {
- lastChunkX = block.m_ChunkX;
- lastChunkZ = block.m_ChunkZ;
- chunk = GetChunk(lastChunkX, lastChunkZ);
- }
-
- // If the chunk is valid, set the block:
- if (chunk != nullptr)
- {
- chunk->SetBlock({block.m_RelX, block.m_RelY, block.m_RelZ}, block.m_BlockType, block.m_BlockMeta);
- }
- } // for block - a_Blocks[]
-}
-
-
-
-
-
void cChunkMap::CollectPickupsByPlayer(cPlayer & a_Player)
{
int BlockX = static_cast<int>(a_Player.GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
@@ -637,15 +609,7 @@ void cChunkMap::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE
auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
if ((chunk != nullptr) && chunk->IsValid())
{
- BLOCKTYPE blockType;
- NIBBLETYPE blockMeta;
- GetBlockTypeMeta(a_BlockPos, blockType, blockMeta);
- cChunkInterface ChunkInterface(this);
-
- BlockHandler(blockType)->OnBroken(ChunkInterface, *m_World, a_BlockPos, blockType, blockMeta);
-
chunk->SetBlock(relPos, a_BlockType, a_BlockMeta);
- BlockHandler(a_BlockType)->OnPlaced(ChunkInterface, *m_World, a_BlockPos, a_BlockType, a_BlockMeta);
}
}
@@ -692,28 +656,6 @@ bool cChunkMap::GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBL
-void cChunkMap::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType)
-{
- cCSLock Lock(m_CSChunks);
- for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
- {
- auto chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
- if ((chunk == nullptr) || !chunk->IsValid())
- {
- continue;
- }
- Vector3i relPos(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
- if (chunk->GetBlock(relPos) == a_FilterBlockType)
- {
- chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta);
- }
- }
-}
-
-
-
-
-
void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
{
cCSLock Lock(m_CSChunks);
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 685651728..c6fb6dc18 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -132,11 +132,6 @@ public:
If the chunk is invalid, the operation is ignored silently. */
void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- /** Performs the specified single-block set operations simultaneously, as if SetBlock() was called for each item.
- Is more efficient than calling SetBlock() multiple times.
- If the chunk for any of the blocks is not loaded, the set operation is ignored silently. */
- void SetBlocks(const sSetBlockVector & a_Blocks);
-
/** Makes the specified player collect all the pickups around them. */
void CollectPickupsByPlayer(cPlayer & a_Player);
@@ -155,9 +150,6 @@ public:
bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
bool GetBlockInfo (Vector3i, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
- /** Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType */
- void ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType);
-
/** Special function used for growing trees, replaces only blocks that tree may overwrite */
void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 9dc1274d1..c12e11f45 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -1373,7 +1373,6 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
cChunkInterface ChunkInterface(World->GetChunkMap());
auto blockHandler = BlockHandler(a_OldBlock);
Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ);
- blockHandler->OnPlayerBreakingBlock(ChunkInterface, *World, *m_Player, absPos);
if (m_Player->IsGameModeSurvival())
{
World->DropBlockAsPickups(absPos, m_Player, &m_Player->GetEquippedItem());
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 9ceded8b2..3bfcb4039 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -2910,22 +2910,20 @@ bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
}
} // for blk - a_Blocks[]
- // Set the blocks:
- m_World->SetBlocks(a_Blocks);
-
- // Notify the blockhandlers:
cChunkInterface ChunkInterface(m_World->GetChunkMap());
for (auto blk: a_Blocks)
{
+ // Set the blocks:
+ m_World->PlaceBlock(blk.GetAbsolutePos(), blk.m_BlockType, blk.m_BlockMeta);
+
+ // Notify the blockhandlers:
cBlockHandler * newBlock = BlockHandler(blk.m_BlockType);
newBlock->OnPlacedByPlayer(ChunkInterface, *m_World, *this, blk);
- }
- // Call the "placed" hooks:
- for (auto blk: a_Blocks)
- {
+ // Call the "placed" hooks:
pm->CallHookPlayerPlacedBlock(*this, blk);
}
+
return true;
}
diff --git a/src/Items/ItemChest.h b/src/Items/ItemChest.h
index 014ccc3e6..ecd957a59 100644
--- a/src/Items/ItemChest.h
+++ b/src/Items/ItemChest.h
@@ -54,7 +54,6 @@ public:
Vector3i PlacePos;
if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta))
{
- blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, a_ClickedBlockPos);
PlacePos = a_ClickedBlockPos;
}
else
@@ -75,7 +74,6 @@ public:
{
return false;
}
- blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, PlacePos);
}
// Check that there is at most one single neighbor of the same chest type:
diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h
index d4469a31b..a7e192ee6 100644
--- a/src/Items/ItemLighter.h
+++ b/src/Items/ItemLighter.h
@@ -65,7 +65,7 @@ public:
case E_BLOCK_TNT:
{
// Activate the TNT:
- a_World->SetBlock(a_ClickedBlockPos, E_BLOCK_AIR, 0);
+ a_World->DigBlock(a_ClickedBlockPos);
a_World->SpawnPrimedTNT(Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom
break;
}
@@ -79,7 +79,7 @@ public:
}
if (a_World->GetBlock(FirePos) == E_BLOCK_AIR)
{
- a_World->SetBlock(FirePos, E_BLOCK_FIRE, 0);
+ a_World->PlaceBlock(FirePos, E_BLOCK_FIRE, 0);
a_World->BroadcastSoundEffect("item.flintandsteel.use", FirePos, 1.0f, 1.04f);
break;
}
diff --git a/src/World.cpp b/src/World.cpp
index 4de325d6e..f70343889 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2182,18 +2182,12 @@ UInt32 cWorld::SpawnPrimedTNT(Vector3d a_Pos, int a_FuseTicks, double a_InitialV
-void cWorld::SetBlocks(const sSetBlockVector & a_Blocks)
+void cWorld::PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta)
{
- m_ChunkMap->SetBlocks(a_Blocks);
-}
-
-
-
-
+ SetBlock(a_Position, a_BlockType, a_BlockMeta);
-void cWorld::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType)
-{
- m_ChunkMap->ReplaceBlocks(a_Blocks, a_FilterBlockType);
+ cChunkInterface ChunkInterface(GetChunkMap());
+ cBlockInfo::GetHandler(a_BlockType)->OnPlaced(ChunkInterface, *this, a_Position, a_BlockType, a_BlockMeta);
}
@@ -2211,17 +2205,18 @@ bool cWorld::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
bool cWorld::DigBlock(Vector3i a_BlockPos)
{
- BLOCKTYPE blockType;
- NIBBLETYPE blockMeta;
- GetBlockTypeMeta(a_BlockPos, blockType, blockMeta);
- cChunkInterface chunkInterface(GetChunkMap());
- auto blockHandler = cBlockInfo::GetHandler(blockType);
- blockHandler->OnBreaking(chunkInterface, *this, a_BlockPos);
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
+
if (!m_ChunkMap->DigBlock(a_BlockPos))
{
return false;
}
- blockHandler->OnBroken(chunkInterface, *this, a_BlockPos, blockType, blockMeta);
+
+ cChunkInterface ChunkInterface(GetChunkMap());
+ cBlockInfo::GetHandler(BlockType)->OnBroken(ChunkInterface, *this, a_BlockPos, BlockType, BlockMeta);
+
return true;
}
diff --git a/src/World.h b/src/World.h
index 76c0fa3c9..b6936a9d5 100644
--- a/src/World.h
+++ b/src/World.h
@@ -661,22 +661,18 @@ public:
// tolua_end
- /** Performs the specified single-block set operations simultaneously, as if SetBlock() was called for each item.
- Is more efficient than calling SetBlock() multiple times.
+ /** Replaces the specified block with another, and calls the OnPlaced block handler.
+ Callers MUST ensure the replaced block was destroyed or can handle replacement correctly. Wakes up the simulators.
If the chunk for any of the blocks is not loaded, the set operation is ignored silently. */
- void SetBlocks(const sSetBlockVector & a_Blocks);
-
- /** Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType */
- void ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType);
+ void PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta);
/** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */
bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure);
// tolua_begin
- /** Replaces the specified block with air, and calls the apropriate block handlers (OnBreaking(), OnBroken()).
- Wakes up the simulators.
- Doesn't produce pickups, use DropBlockAsPickups() for that instead.
+ /** Replaces the specified block with air, and calls the OnBroken block handler.
+ Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead.
Returns true on success, false if the chunk is not loaded. */
bool DigBlock(Vector3i a_BlockPos);