OnBroken/OnPlaced are for entity actions
* Call OnPlaced/OnBroken in PlaceBlock/DigBlock - Remove unused Placing/Breaking handlers * Have the blockhandler's Check handle neighbour updating, instead of QueueTickBlockNeighbors
This commit is contained in:
parent
adb86a75da
commit
6bdd130aab
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** 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)
|
||||
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
|
||||
{
|
||||
static const std::array<Vector3i, 5> WaterCheck
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{ 0, 0, 1},
|
||||
{ 0, 0, -1},
|
||||
{ 0, 1, 0},
|
||||
}
|
||||
};
|
||||
a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { CheckSoaked(a_Chunk.AbsoluteToRelative(a_BlockPos), a_Chunk); return true; });
|
||||
}
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
);
|
||||
/** 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)
|
||||
{
|
||||
const auto & WaterCheck = cSimulator::AdjacentOffsets;
|
||||
const 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)
|
||||
);
|
||||
});
|
||||
|
||||
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:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
if (a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { return CanBeAt(a_ChunkInterface, a_Chunk.AbsoluteToRelative(a_BlockPos), a_Chunk); }))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)));
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
14
src/World.h
14
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user