Corrected wakeup sequences
* Pistons/Ice no longer need to FastSetBlock first (#4600), and the former don't drop items when broken in creative - Begin migration away from stationary fluids * Tick the chunk after applying a client's changed * Broadcast pending blocks at the end of a tick
This commit is contained in:
parent
6bdd130aab
commit
c3d6afe47e
@ -43,32 +43,6 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual void Check(
|
||||
cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
||||
Vector3i a_RelPos,
|
||||
cChunk & a_Chunk
|
||||
) override
|
||||
{
|
||||
switch (m_BlockType)
|
||||
{
|
||||
case E_BLOCK_STATIONARY_LAVA:
|
||||
{
|
||||
a_Chunk.FastSetBlock(a_RelPos, E_BLOCK_LAVA, a_Chunk.GetMeta(a_RelPos));
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_STATIONARY_WATER:
|
||||
{
|
||||
a_Chunk.FastSetBlock(a_RelPos, E_BLOCK_WATER, a_Chunk.GetMeta(a_RelPos));
|
||||
break;
|
||||
}
|
||||
}
|
||||
Super::Check(a_ChunkInterface, a_PluginInterface, a_RelPos, a_Chunk);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
@ -19,10 +19,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override
|
||||
{
|
||||
// Only drop self when using silk-touch:
|
||||
@ -36,10 +32,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void OnBroken(
|
||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
||||
Vector3i a_BlockPos,
|
||||
@ -51,19 +43,14 @@ public:
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto blockTypeBelow = a_ChunkInterface.GetBlock(a_BlockPos.addedY(-1));
|
||||
if (cBlockInfo::FullyOccupiesVoxel(blockTypeBelow) || IsBlockLiquid(blockTypeBelow))
|
||||
|
||||
const auto Below = a_ChunkInterface.GetBlock(a_BlockPos.addedY(-1));
|
||||
if (cBlockInfo::FullyOccupiesVoxel(Below) || IsBlockLiquid(Below))
|
||||
{
|
||||
// Setting air with FastSetBlock prevents SetBlock recursively calling OnBroken.
|
||||
a_ChunkInterface.FastSetBlock(a_BlockPos, E_BLOCK_AIR, 0);
|
||||
a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_WATER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
@ -32,14 +32,19 @@ void cBlockPistonHandler::OnBroken(
|
||||
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
|
||||
)
|
||||
{
|
||||
// If the piston is extended, destroy the extension as well
|
||||
if (IsExtended(a_OldBlockMeta))
|
||||
if (!IsExtended(a_OldBlockMeta))
|
||||
{
|
||||
auto extPos = a_BlockPos + MetadataToOffset(a_OldBlockMeta);
|
||||
if (a_ChunkInterface.GetBlock(extPos) == E_BLOCK_PISTON_EXTENSION)
|
||||
{
|
||||
a_ChunkInterface.DropBlockAsPickups(extPos);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const auto Extension = a_BlockPos + MetadataToOffset(a_OldBlockMeta);
|
||||
if (
|
||||
cChunkDef::IsValidHeight(Extension.y) &&
|
||||
(a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION)
|
||||
)
|
||||
{
|
||||
// If the piston is extended, destroy the extension as well:
|
||||
a_ChunkInterface.SetBlock(Extension, E_BLOCK_AIR, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +80,7 @@ void cBlockPistonHandler::PushBlocks(
|
||||
cWorld & a_World, const Vector3i & a_PushDir
|
||||
)
|
||||
{
|
||||
// Sort blocks to move the blocks first, which are farest away from the piston
|
||||
// Sort blocks to move the blocks first, which are farthest away from the piston
|
||||
// This prevents the overwriting of existing blocks
|
||||
std::vector<Vector3i> sortedBlocks(a_BlocksToPush.begin(), a_BlocksToPush.end());
|
||||
std::sort(sortedBlocks.begin(), sortedBlocks.end(), [a_PushDir](const Vector3i & a, const Vector3i & b)
|
||||
@ -281,8 +286,7 @@ void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld & a_World)
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove extension, update base state. Calling FastSetBlock inhibits OnBroken being called by SetBlock.
|
||||
World.FastSetBlock(extensionPos, E_BLOCK_AIR, 0);
|
||||
// Remove extension, update base state:
|
||||
World.SetBlock(extensionPos, E_BLOCK_AIR, 0);
|
||||
World.SetBlock(a_BlockPos, pistonBlock, pistonMeta & ~(8));
|
||||
|
||||
@ -334,11 +338,17 @@ void cBlockPistonHeadHandler::OnBroken(
|
||||
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
|
||||
)
|
||||
{
|
||||
// Drop the base of the piston:
|
||||
auto basePos = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta);
|
||||
if (cChunkDef::IsValidHeight(basePos.y))
|
||||
const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta);
|
||||
if (!cChunkDef::IsValidHeight(Base.y))
|
||||
{
|
||||
a_ChunkInterface.DropBlockAsPickups(basePos);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto Block = a_ChunkInterface.GetBlock(Base);
|
||||
if ((Block == E_BLOCK_PISTON) || (Block == E_BLOCK_STICKY_PISTON))
|
||||
{
|
||||
// Remove the base of the piston:
|
||||
a_ChunkInterface.SetBlock(Base, E_BLOCK_AIR, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,3 +356,9 @@ void cBlockPistonHeadHandler::OnBroken(
|
||||
|
||||
|
||||
|
||||
cItems cBlockPistonHeadHandler::ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool)
|
||||
{
|
||||
// Give a normal\sticky piston base, not piston extension
|
||||
// With 1.7, the item forms of these technical blocks have been removed, so giving someone this will crash their client...
|
||||
return { cItem(((a_BlockMeta & 0x8) == 0x8) ? E_BLOCK_STICKY_PISTON : E_BLOCK_PISTON) };
|
||||
}
|
||||
|
@ -155,10 +155,5 @@ public:
|
||||
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
|
||||
) override;
|
||||
|
||||
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override
|
||||
{
|
||||
// No pickups
|
||||
// Also with 1.7, the item forms of these technical blocks have been removed, so giving someone this will crash their client...
|
||||
return {};
|
||||
}
|
||||
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override;
|
||||
} ;
|
||||
|
@ -19,44 +19,25 @@ 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 around the sponge to see if they are water.
|
||||
If a dry sponge is touching water, soak up up to 65 blocks of water,
|
||||
with a taxicab distance of 7, and turn the sponge into a wet sponge.
|
||||
Returns TRUE if the block was changed. */
|
||||
bool GetSoaked(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
with a taxicab distance of 7, and turn the sponge into a wet sponge. */
|
||||
void CheckSoaked(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
{
|
||||
static const std::array<Vector3i, 6> WaterCheck
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{ 0, 0, 1},
|
||||
{ 0, 0, -1},
|
||||
{ 0, 1, 0},
|
||||
{ 0, -1, 0},
|
||||
}
|
||||
};
|
||||
struct sSeed
|
||||
{
|
||||
sSeed(Vector3i pos, int d)
|
||||
@ -68,27 +49,25 @@ public:
|
||||
int m_Depth;
|
||||
};
|
||||
|
||||
|
||||
// Check if this is a dry sponge next to a water block.
|
||||
NIBBLETYPE TargetMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z);
|
||||
if (TargetMeta != E_META_SPONGE_DRY)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, & a_Chunk](Vector3i a_Offset)
|
||||
{
|
||||
return IsWet(a_Rel + a_Offset, a_Chunk);
|
||||
}
|
||||
);
|
||||
const auto & WaterCheck = cSimulator::AdjacentOffsets;
|
||||
const bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, &a_Chunk](Vector3i a_Offset)
|
||||
{
|
||||
return IsWet(a_Rel + a_Offset, a_Chunk);
|
||||
});
|
||||
|
||||
// Early return if the sponge isn't touching any water.
|
||||
if (! ShouldSoak)
|
||||
if (!ShouldSoak)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Use a queue to hold blocks that we want to check, so our search is breadth-first.
|
||||
std::queue<sSeed> Seeds;
|
||||
int count = 0;
|
||||
@ -100,7 +79,6 @@ public:
|
||||
Seeds.emplace(a_Rel + WaterCheck[i], maxDepth - 1);
|
||||
}
|
||||
|
||||
|
||||
// Keep checking blocks that are touching water blocks, or until 65 have been soaked up.
|
||||
while (!Seeds.empty() && count < 65)
|
||||
{
|
||||
@ -122,24 +100,16 @@ public:
|
||||
}
|
||||
Seeds.pop();
|
||||
}
|
||||
|
||||
a_Chunk.SetBlock(a_Rel, E_BLOCK_SPONGE, E_META_SPONGE_WET);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void DryUp(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: support evaporating waterlogged blocks.
|
||||
a_Chunk.UnboundedRelSetBlock(a_Rel.x, a_Rel.y, a_Rel.z, E_BLOCK_AIR, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static bool IsWet(Vector3i a_Rel, cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: support detecting waterlogged blocks.
|
||||
@ -147,18 +117,9 @@ public:
|
||||
return(a_Chunk.UnboundedRelGetBlockType(a_Rel.x, a_Rel.y, a_Rel.z, Type) && IsBlockWater(Type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
return 18;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
@ -162,12 +162,12 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual void Check(
|
||||
cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface,
|
||||
Vector3i a_RelPos,
|
||||
cChunk & a_Chunk
|
||||
) override
|
||||
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
|
||||
{
|
||||
a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk)
|
||||
{
|
||||
|
||||
const auto a_RelPos = a_Chunk.AbsoluteToRelative(a_BlockPos);
|
||||
NIBBLETYPE CurMeta = a_Chunk.GetMeta(a_RelPos);
|
||||
NIBBLETYPE MaxMeta = GetMaxMeta(a_Chunk, a_RelPos);
|
||||
|
||||
@ -190,14 +190,13 @@ public:
|
||||
a_ChunkInterface.DropBlockAsPickups(a_Chunk.RelativeToAbsolute(a_RelPos));
|
||||
}
|
||||
a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
a_Chunk.SetBlock(a_RelPos, m_BlockType, Common);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Chunk.GetWorld()->GetSimulatorManager()->WakeUp(a_Chunk, a_RelPos);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -651,8 +651,6 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||
return;
|
||||
}
|
||||
|
||||
BroadcastPendingBlockChanges();
|
||||
|
||||
CheckBlocks();
|
||||
|
||||
// Tick simulators:
|
||||
@ -716,6 +714,8 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||
} // for itr - m_Entitites[]
|
||||
|
||||
ApplyWeatherToTop();
|
||||
|
||||
BroadcastPendingBlockChanges();
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,7 +121,7 @@ void cDelayedFluidSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a
|
||||
|
||||
void cDelayedFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||
{
|
||||
if (a_Block != m_FluidBlock)
|
||||
if ((a_Block != m_FluidBlock) && (a_Block != m_StationaryFluidBlock))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
virtual ~cSimulator() {}
|
||||
|
||||
// Contains our direct adjacents
|
||||
inline static std::array<Vector3i, 6> AdjacentOffsets
|
||||
static constexpr std::array<Vector3i, 6> AdjacentOffsets
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
|
@ -1036,12 +1036,11 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La
|
||||
// Add players waiting in the queue to be added:
|
||||
AddQueuedPlayers();
|
||||
|
||||
m_ChunkMap->Tick(a_Dt);
|
||||
TickMobs(a_Dt);
|
||||
m_MapManager.TickMaps();
|
||||
|
||||
TickClients(static_cast<float>(a_Dt.count()));
|
||||
TickQueuedBlocks();
|
||||
m_ChunkMap->Tick(a_Dt); // Tick chunk after clients to apply at least one round of queued ticks (e.g. cBlockHandler::Check) this tick
|
||||
TickMobs(a_Dt);
|
||||
m_MapManager.TickMaps();
|
||||
TickQueuedTasks();
|
||||
|
||||
GetSimulatorManager()->Simulate(static_cast<float>(a_Dt.count()));
|
||||
|
Loading…
Reference in New Issue
Block a user