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 OnPlaced(
|
||||||
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
||||||
|
Vector3i a_BlockPos,
|
||||||
|
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
|
||||||
virtual void Check(
|
|
||||||
cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
|
||||||
Vector3i a_RelPos,
|
|
||||||
cChunk & a_Chunk
|
|
||||||
) override
|
) override
|
||||||
{
|
{
|
||||||
if (GetSoaked(a_RelPos, a_Chunk))
|
OnNeighborChanged(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NONE);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Super::Check(a_ChunkInterface, a_PluginInterface, a_RelPos, a_Chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 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)
|
|
||||||
{
|
{
|
||||||
static const std::array<Vector3i, 5> WaterCheck
|
a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { CheckSoaked(a_Chunk.AbsoluteToRelative(a_BlockPos), a_Chunk); return true; });
|
||||||
{
|
|
||||||
{
|
|
||||||
{ 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)
|
/** 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;
|
BLOCKTYPE NeighborType;
|
||||||
return (
|
return (
|
||||||
a_Chunk.UnboundedRelGetBlockType(a_Rel.x + a_Offset.x, a_Rel.y + a_Offset.y, a_Rel.z + a_Offset.z, NeighborType)
|
a_Chunk.UnboundedRelGetBlockType(a_Rel.x + a_Offset.x, a_Rel.y + a_Offset.y, a_Rel.z + a_Offset.z, NeighborType)
|
||||||
&& IsBlockWater(NeighborType)
|
&& IsBlockWater(NeighborType)
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (ShouldSoak)
|
if (ShouldSoak)
|
||||||
{
|
{
|
||||||
NIBBLETYPE BlockMeta;
|
NIBBLETYPE BlockMeta;
|
||||||
BlockMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z);
|
BlockMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z);
|
||||||
a_Chunk.SetBlock(a_Rel, E_BLOCK_CONCRETE, BlockMeta);
|
a_Chunk.SetBlock(a_Rel, E_BLOCK_CONCRETE, BlockMeta);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||||
{
|
{
|
||||||
switch (a_Meta)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DoesDropOnUnsuitable())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockHandler::OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
|
||||||
{
|
{
|
||||||
// Notify the neighbors
|
a_ChunkInterface.DropBlockAsPickups(a_BlockPos);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta)
|
|
||||||
{
|
{
|
||||||
// Notify the neighbors
|
a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_AIR, 0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -585,19 +567,13 @@ void cBlockHandler::Check(
|
|||||||
cChunk & a_Chunk
|
cChunk & a_Chunk
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (CanBeAt(a_ChunkInterface, a_RelPos, a_Chunk))
|
const auto Position = cChunkDef::RelativeToAbsolute(a_RelPos, a_Chunk.GetPos());
|
||||||
{
|
NeighborChanged(a_ChunkInterface, Position.addedX(-1), BLOCK_FACE_XP);
|
||||||
return;
|
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);
|
||||||
if (DoesDropOnUnsuitable())
|
NeighborChanged(a_ChunkInterface, Position.addedZ(-1), BLOCK_FACE_ZP);
|
||||||
{
|
NeighborChanged(a_ChunkInterface, Position.addedZ(1), BLOCK_FACE_ZM);
|
||||||
a_ChunkInterface.DropBlockAsPickups(a_Chunk.RelativeToAbsolute(a_RelPos));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,21 +65,12 @@ public:
|
|||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
||||||
Vector3i a_BlockPos,
|
Vector3i a_BlockPos,
|
||||||
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
|
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
|
||||||
);
|
) {};
|
||||||
|
|
||||||
/** Called by cPlayer::PlaceBlocks() for each block after it has been set to the world. Called after OnPlaced(). */
|
/** Called by cPlayer::PlaceBlocks() for each block after it has been set to the world. Called after OnPlaced(). */
|
||||||
virtual void OnPlacedByPlayer(
|
virtual void OnPlacedByPlayer(
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange
|
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.
|
/** 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.
|
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
|
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.
|
/** 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.
|
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.
|
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,
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
||||||
Vector3i a_BlockPos,
|
Vector3i a_BlockPos,
|
||||||
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
|
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
|
||||||
);
|
) {};
|
||||||
|
|
||||||
/** Called when a direct neighbor of this block has been changed.
|
/** 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.
|
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.
|
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.) */
|
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.
|
/** Notifies the specified neighbor that the current block has changed.
|
||||||
a_NeighborPos are the coords of the neighbor to be notified
|
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.
|
/** 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()),
|
By default drops (DropBlockAsPickup() / SetBlock()) if the position is no longer suitable (CanBeAt(), DoesDropOnUnsuitable()),
|
||||||
otherwise wakes up all simulators on the block. */
|
otherwise wakes up all simulators on the block. */
|
||||||
virtual void Check(
|
void Check(
|
||||||
cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
||||||
Vector3i a_RelPos,
|
Vector3i a_RelPos,
|
||||||
cChunk & a_Chunk
|
cChunk & a_Chunk
|
||||||
|
@ -44,7 +44,7 @@ public:
|
|||||||
}
|
}
|
||||||
case paDeath:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case paStay: break; // do nothing
|
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)
|
BLOCKTYPE cChunkInterface::GetBlock(Vector3i a_Pos)
|
||||||
{
|
{
|
||||||
return m_ChunkMap->GetBlock(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)
|
bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos)
|
||||||
{
|
{
|
||||||
BLOCKTYPE blockType;
|
BLOCKTYPE BlockType;
|
||||||
NIBBLETYPE blockMeta;
|
NIBBLETYPE BlockMeta;
|
||||||
GetBlockTypeMeta(a_BlockPos, blockType, blockMeta);
|
GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
|
||||||
auto handler = cBlockInfo::GetHandler(blockType);
|
|
||||||
handler->OnBreaking(*this, a_WorldInterface, a_BlockPos);
|
|
||||||
if (!m_ChunkMap->DigBlock(a_BlockPos))
|
if (!m_ChunkMap->DigBlock(a_BlockPos))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
handler->OnBroken(*this, a_WorldInterface, a_BlockPos, blockType, blockMeta);
|
|
||||||
|
cBlockInfo::GetHandler(BlockType)->OnBroken(*this, a_WorldInterface, a_BlockPos, BlockType, BlockMeta);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../ForEachChunkProvider.h"
|
#include "../ForEachChunkProvider.h"
|
||||||
|
#include "../FunctionRef.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fwd:
|
// fwd:
|
||||||
class cItem;
|
class cItem;
|
||||||
|
class cChunk;
|
||||||
class cChunkMap;
|
class cChunkMap;
|
||||||
class cWorldInterface;
|
class cWorldInterface;
|
||||||
class cPlayer;
|
class cPlayer;
|
||||||
@ -23,6 +25,8 @@ public:
|
|||||||
|
|
||||||
cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {}
|
cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {}
|
||||||
|
|
||||||
|
bool DoWithChunkAt(Vector3i a_BlockPos, cFunctionRef<bool(cChunk &)> a_Callback);
|
||||||
|
|
||||||
BLOCKTYPE GetBlock(Vector3i a_Pos);
|
BLOCKTYPE GetBlock(Vector3i a_Pos);
|
||||||
NIBBLETYPE GetBlockMeta(Vector3i a_Pos);
|
NIBBLETYPE GetBlockMeta(Vector3i a_Pos);
|
||||||
|
|
||||||
|
@ -820,7 +820,7 @@ void cChunk::CheckBlocks()
|
|||||||
|
|
||||||
while (Count != 0)
|
while (Count != 0)
|
||||||
{
|
{
|
||||||
Vector3i Pos = m_ToTickBlocks.front();
|
const auto Pos = m_ToTickBlocks.front();
|
||||||
m_ToTickBlocks.pop();
|
m_ToTickBlocks.pop();
|
||||||
Count--;
|
Count--;
|
||||||
|
|
||||||
@ -1263,8 +1263,8 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
|
|||||||
{
|
{
|
||||||
FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta);
|
FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta);
|
||||||
|
|
||||||
// Tick this block and its neighbors:
|
// Tick this block's neighbors via cBlockHandler::Check:
|
||||||
QueueTickBlockNeighbors(a_RelPos);
|
m_ToTickBlocks.push(a_RelPos);
|
||||||
|
|
||||||
// Wake up the simulators for this block:
|
// Wake up the simulators for this block:
|
||||||
GetWorld()->GetSimulatorManager()->WakeUp(*this, a_RelPos);
|
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)
|
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)));
|
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);
|
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
|
// 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(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)
|
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)
|
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
|
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);
|
auto chunk = GetChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
||||||
if ((chunk != nullptr) && chunk->IsValid())
|
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);
|
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)
|
void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSChunks);
|
cCSLock Lock(m_CSChunks);
|
||||||
|
@ -132,11 +132,6 @@ public:
|
|||||||
If the chunk is invalid, the operation is ignored silently. */
|
If the chunk is invalid, the operation is ignored silently. */
|
||||||
void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
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. */
|
/** Makes the specified player collect all the pickups around them. */
|
||||||
void CollectPickupsByPlayer(cPlayer & a_Player);
|
void CollectPickupsByPlayer(cPlayer & a_Player);
|
||||||
|
|
||||||
@ -155,9 +150,6 @@ public:
|
|||||||
bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
|
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);
|
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 */
|
/** Special function used for growing trees, replaces only blocks that tree may overwrite */
|
||||||
void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
|
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());
|
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||||
auto blockHandler = BlockHandler(a_OldBlock);
|
auto blockHandler = BlockHandler(a_OldBlock);
|
||||||
Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ);
|
Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
blockHandler->OnPlayerBreakingBlock(ChunkInterface, *World, *m_Player, absPos);
|
|
||||||
if (m_Player->IsGameModeSurvival())
|
if (m_Player->IsGameModeSurvival())
|
||||||
{
|
{
|
||||||
World->DropBlockAsPickups(absPos, m_Player, &m_Player->GetEquippedItem());
|
World->DropBlockAsPickups(absPos, m_Player, &m_Player->GetEquippedItem());
|
||||||
|
@ -2910,22 +2910,20 @@ bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
|
|||||||
}
|
}
|
||||||
} // for blk - a_Blocks[]
|
} // for blk - a_Blocks[]
|
||||||
|
|
||||||
// Set the blocks:
|
|
||||||
m_World->SetBlocks(a_Blocks);
|
|
||||||
|
|
||||||
// Notify the blockhandlers:
|
|
||||||
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
||||||
for (auto blk: a_Blocks)
|
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);
|
cBlockHandler * newBlock = BlockHandler(blk.m_BlockType);
|
||||||
newBlock->OnPlacedByPlayer(ChunkInterface, *m_World, *this, blk);
|
newBlock->OnPlacedByPlayer(ChunkInterface, *m_World, *this, blk);
|
||||||
}
|
|
||||||
|
|
||||||
// Call the "placed" hooks:
|
// Call the "placed" hooks:
|
||||||
for (auto blk: a_Blocks)
|
|
||||||
{
|
|
||||||
pm->CallHookPlayerPlacedBlock(*this, blk);
|
pm->CallHookPlayerPlacedBlock(*this, blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ public:
|
|||||||
Vector3i PlacePos;
|
Vector3i PlacePos;
|
||||||
if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta))
|
if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta))
|
||||||
{
|
{
|
||||||
blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, a_ClickedBlockPos);
|
|
||||||
PlacePos = a_ClickedBlockPos;
|
PlacePos = a_ClickedBlockPos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -75,7 +74,6 @@ public:
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, PlacePos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is at most one single neighbor of the same chest type:
|
// Check that there is at most one single neighbor of the same chest type:
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
case E_BLOCK_TNT:
|
case E_BLOCK_TNT:
|
||||||
{
|
{
|
||||||
// Activate the 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
|
a_World->SpawnPrimedTNT(Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public:
|
|||||||
}
|
}
|
||||||
if (a_World->GetBlock(FirePos) == E_BLOCK_AIR)
|
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);
|
a_World->BroadcastSoundEffect("item.flintandsteel.use", FirePos, 1.0f, 1.04f);
|
||||||
break;
|
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);
|
||||||
}
|
|
||||||
|
|
||||||
|
cChunkInterface ChunkInterface(GetChunkMap());
|
||||||
|
cBlockInfo::GetHandler(a_BlockType)->OnPlaced(ChunkInterface, *this, a_Position, a_BlockType, a_BlockMeta);
|
||||||
|
|
||||||
|
|
||||||
void cWorld::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType)
|
|
||||||
{
|
|
||||||
m_ChunkMap->ReplaceBlocks(a_Blocks, a_FilterBlockType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2211,17 +2205,18 @@ bool cWorld::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
|||||||
|
|
||||||
bool cWorld::DigBlock(Vector3i a_BlockPos)
|
bool cWorld::DigBlock(Vector3i a_BlockPos)
|
||||||
{
|
{
|
||||||
BLOCKTYPE blockType;
|
BLOCKTYPE BlockType;
|
||||||
NIBBLETYPE blockMeta;
|
NIBBLETYPE BlockMeta;
|
||||||
GetBlockTypeMeta(a_BlockPos, blockType, blockMeta);
|
GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
|
||||||
cChunkInterface chunkInterface(GetChunkMap());
|
|
||||||
auto blockHandler = cBlockInfo::GetHandler(blockType);
|
|
||||||
blockHandler->OnBreaking(chunkInterface, *this, a_BlockPos);
|
|
||||||
if (!m_ChunkMap->DigBlock(a_BlockPos))
|
if (!m_ChunkMap->DigBlock(a_BlockPos))
|
||||||
{
|
{
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/World.h
14
src/World.h
@ -661,22 +661,18 @@ public:
|
|||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
/** Performs the specified single-block set operations simultaneously, as if SetBlock() was called for each item.
|
/** Replaces the specified block with another, and calls the OnPlaced block handler.
|
||||||
Is more efficient than calling SetBlock() multiple times.
|
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. */
|
If the chunk for any of the blocks is not loaded, the set operation is ignored silently. */
|
||||||
void SetBlocks(const sSetBlockVector & a_Blocks);
|
void PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta);
|
||||||
|
|
||||||
/** Replaces world blocks with a_Blocks, if they are of type a_FilterBlockType */
|
|
||||||
void ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType);
|
|
||||||
|
|
||||||
/** 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. */
|
/** 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);
|
bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure);
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
/** Replaces the specified block with air, and calls the apropriate block handlers (OnBreaking(), OnBroken()).
|
/** Replaces the specified block with air, and calls the OnBroken block handler.
|
||||||
Wakes up the simulators.
|
Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead.
|
||||||
Doesn't produce pickups, use DropBlockAsPickups() for that instead.
|
|
||||||
Returns true on success, false if the chunk is not loaded. */
|
Returns true on success, false if the chunk is not loaded. */
|
||||||
bool DigBlock(Vector3i a_BlockPos);
|
bool DigBlock(Vector3i a_BlockPos);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user