mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-07 03:16:55 +08:00
Clean up CanBeAt Functions (#5587)
* Use cChunkDef::IsValidHeight for CanBeAt functions, and related helpers. * Add mixins for SolidSurfaceUnderneat and DirtLikeUnderneath * Minor fixes after change review.
This commit is contained in:
parent
a99c3ec2b8
commit
ab62fc3988
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../UI/AnvilWindow.h"
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "BlockEntity.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "Entities/Player.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -25,9 +25,10 @@ private:
|
||||
if (IsMetaTopPart(a_Meta))
|
||||
{
|
||||
BLOCKTYPE BottomType;
|
||||
const auto BottomPosition = a_Position.addedY(-1);
|
||||
if (
|
||||
(a_Position.y < 1) ||
|
||||
!a_World.GetBlockTypeMeta(a_Position - Vector3i(0, 1, 0), BottomType, a_Meta) ||
|
||||
!cChunkDef::IsValidHeight(BottomPosition) ||
|
||||
!a_World.GetBlockTypeMeta(BottomPosition, BottomType, a_Meta) ||
|
||||
(BottomType != E_BLOCK_BIG_FLOWER)
|
||||
)
|
||||
{
|
||||
@ -104,7 +105,7 @@ private:
|
||||
// Both parts can only that they're rooted in grass.
|
||||
|
||||
const auto RootPosition = a_Position.addedY(IsMetaTopPart(a_Meta) ? -2 : -1);
|
||||
return (RootPosition.y >= 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition));
|
||||
return cChunkDef::IsValidHeight(RootPosition) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "../Chunk.h"
|
||||
#include "Defines.h"
|
||||
#include "Entities/Player.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "World.h"
|
||||
|
||||
|
@ -20,11 +20,12 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto SurfacePosition = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(SurfacePosition))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BLOCKTYPE Surface = a_Chunk.GetBlock(a_Position.addedY(-1));
|
||||
BLOCKTYPE Surface = a_Chunk.GetBlock(SurfacePosition);
|
||||
if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS))
|
||||
{
|
||||
// Cactus can only be placed on sand and itself
|
||||
@ -75,25 +76,25 @@ private:
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
|
||||
{
|
||||
// Check the total height of the cacti blocks here:
|
||||
int top = a_RelPos.y + 1;
|
||||
auto Top = a_RelPos.addedY(1);
|
||||
while (
|
||||
(top < cChunkDef::Height) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_CACTUS)
|
||||
cChunkDef::IsValidHeight(Top) &&
|
||||
(a_Chunk.GetBlock(Top) == E_BLOCK_CACTUS)
|
||||
)
|
||||
{
|
||||
++top;
|
||||
Top.y++;
|
||||
}
|
||||
int bottom = a_RelPos.y - 1;
|
||||
auto Bottom = a_RelPos.addedY(-1);
|
||||
while (
|
||||
(bottom > 0) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_CACTUS)
|
||||
cChunkDef::IsValidHeight(Bottom) &&
|
||||
(a_Chunk.GetBlock(Bottom) == E_BLOCK_CACTUS)
|
||||
)
|
||||
{
|
||||
--bottom;
|
||||
--Bottom.y;
|
||||
}
|
||||
|
||||
// Refuse if already too high:
|
||||
auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (top - bottom));
|
||||
auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (Top.y - Bottom.y));
|
||||
if (numToGrow <= 0)
|
||||
{
|
||||
return 0;
|
||||
@ -102,14 +103,14 @@ private:
|
||||
BLOCKTYPE blockType;
|
||||
for (int i = 0; i < numToGrow; ++i)
|
||||
{
|
||||
Vector3i pos(a_RelPos.x, top + i, a_RelPos.z);
|
||||
if (!a_Chunk.UnboundedRelGetBlockType(pos, blockType) || (blockType != E_BLOCK_AIR))
|
||||
auto NewTop = Top.addedY(i);
|
||||
if (!a_Chunk.UnboundedRelGetBlockType(NewTop, blockType) || (blockType != E_BLOCK_AIR))
|
||||
{
|
||||
// Cannot grow there
|
||||
return i;
|
||||
}
|
||||
|
||||
a_Chunk.UnboundedRelFastSetBlock(pos, E_BLOCK_CACTUS, 0);
|
||||
a_Chunk.UnboundedRelFastSetBlock(NewTop, E_BLOCK_CACTUS, 0);
|
||||
|
||||
// Check surroundings. Cacti may ONLY be surrounded by non-solid blocks; if they aren't, drop as pickup and bail out the growing
|
||||
static const Vector3i neighborOffsets[] =
|
||||
@ -122,7 +123,7 @@ private:
|
||||
for (const auto & ofs: neighborOffsets)
|
||||
{
|
||||
if (
|
||||
a_Chunk.UnboundedRelGetBlockType(pos + ofs, blockType) &&
|
||||
a_Chunk.UnboundedRelGetBlockType(NewTop + ofs, blockType) &&
|
||||
(
|
||||
cBlockInfo::IsSolid(blockType) ||
|
||||
(blockType == E_BLOCK_LAVA) ||
|
||||
@ -131,7 +132,7 @@ private:
|
||||
)
|
||||
{
|
||||
// Remove the cactus
|
||||
auto absPos = a_Chunk.RelativeToAbsolute(pos);
|
||||
auto absPos = a_Chunk.RelativeToAbsolute(NewTop);
|
||||
a_Chunk.GetWorld()->DropBlockAsPickups(absPos);
|
||||
return i + 1;
|
||||
}
|
||||
@ -143,7 +144,8 @@ private:
|
||||
virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override
|
||||
{
|
||||
// Only allow growing if there's an air block above:
|
||||
if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR))
|
||||
const auto RelPosAbove = a_RelPos.addedY(1);
|
||||
if (cChunkDef::IsValidHeight(RelPosAbove) && (a_Chunk.GetBlock(RelPosAbove) == E_BLOCK_AIR))
|
||||
{
|
||||
return Super::CanGrow(a_Chunk, a_RelPos);
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) != E_BLOCK_AIR);
|
||||
const auto PosBelow = a_Position.addedY(-1);
|
||||
return cChunkDef::IsValidHeight(PosBelow) && (a_Chunk.GetBlock(PosBelow) != E_BLOCK_AIR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "../BlockArea.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -43,7 +43,12 @@ private:
|
||||
auto LogPos = AddFaceDirection(a_Position, BlockFace, true);
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta);
|
||||
if (!a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta))
|
||||
{
|
||||
// Don't pop if chunk not loaded.
|
||||
return true;
|
||||
}
|
||||
|
||||
return ((BlockType == E_BLOCK_LOG) && ((BlockMeta & 0x03) == E_META_LOG_JUNGLE));
|
||||
}
|
||||
|
||||
|
@ -2,17 +2,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "BlockRedstoneRepeater.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "Mixins/SolidSurfaceUnderneath.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockComparatorHandler final :
|
||||
public cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>
|
||||
public cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>
|
||||
{
|
||||
using Super = cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>;
|
||||
using Super = cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>;
|
||||
|
||||
public:
|
||||
|
||||
@ -152,41 +152,6 @@ private:
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// upside down slabs
|
||||
if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
// upside down stairs
|
||||
if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
|
||||
{
|
||||
return cItem(E_ITEM_COMPARATOR, 1, 0);
|
||||
|
@ -118,7 +118,14 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND);
|
||||
const auto BlockBelow = a_Position.addedY(-1);
|
||||
|
||||
if (!cChunkDef::IsValidHeight(BlockBelow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return a_Chunk.GetBlock(BlockBelow) == E_BLOCK_FARMLAND;
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,12 +29,13 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto PosBelow = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(PosBelow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_Position.addedY(-1));
|
||||
BLOCKTYPE BelowBlock = a_Chunk.GetBlock(PosBelow);
|
||||
switch (BelowBlock)
|
||||
{
|
||||
case E_BLOCK_CLAY:
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "../BlockInfo.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../Chunk.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "BlockSlab.h"
|
||||
|
||||
@ -191,14 +191,18 @@ private:
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
// CanBeAt is also called on placement, so the top part can't check for the bottom part.
|
||||
// Both parts can only that their base is a valid block.
|
||||
// Both parts can only check that the base of the door (i.e. -2 for a door top) is a valid block.
|
||||
const auto BasePosition = a_Position.addedY(((a_Meta & 0x8) == 0x8) ? -2 : -1);
|
||||
if (!cChunkDef::IsValidHeight(BasePosition))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
const auto BasePosition = a_Position.addedY(((a_Meta & 0x8) == 0x8) ? -2 : -1);
|
||||
a_Chunk.GetBlockTypeMeta(BasePosition, BlockType, BlockMeta);
|
||||
|
||||
return (BasePosition.y >= 0) && CanBeOn(BlockType, BlockMeta);
|
||||
return CanBeOn(BlockType, BlockMeta);
|
||||
}
|
||||
|
||||
|
||||
@ -216,9 +220,10 @@ private:
|
||||
if ((Meta & 0x08) != 0)
|
||||
{
|
||||
// The coords are pointing at the top part of the door
|
||||
if (a_BlockPos.y > 0)
|
||||
const auto BottomPos = a_BlockPos.addedY(-1);
|
||||
if (cChunkDef::IsValidHeight(BottomPos))
|
||||
{
|
||||
NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(-1));
|
||||
NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(BottomPos);
|
||||
return static_cast<NIBBLETYPE>((DownMeta & 0x07) | 0x08 | (Meta << 4));
|
||||
}
|
||||
// This is the top part of the door at the bottommost layer of the world, there's no bottom:
|
||||
@ -227,9 +232,10 @@ private:
|
||||
else
|
||||
{
|
||||
// The coords are pointing at the bottom part of the door
|
||||
if (a_BlockPos.y < cChunkDef::Height - 1)
|
||||
const auto TopPos = a_BlockPos.addedY(1);
|
||||
if (cChunkDef::IsValidHeight(TopPos))
|
||||
{
|
||||
NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(1));
|
||||
NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(TopPos);
|
||||
return static_cast<NIBBLETYPE>(Meta | (UpMeta << 4));
|
||||
}
|
||||
// This is the bottom part of the door at the topmost layer of the world, there's no top:
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "../EffectID.h"
|
||||
|
||||
|
||||
|
@ -2,15 +2,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins/DirtLikeUnderneath.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockFlowerHandler final :
|
||||
public cBlockHandler
|
||||
public cDirtLikeUnderneath<cBlockHandler>
|
||||
{
|
||||
using Super = cBlockHandler;
|
||||
using Super = cDirtLikeUnderneath<cBlockHandler>;
|
||||
|
||||
public:
|
||||
|
||||
@ -28,15 +29,6 @@ private:
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return (a_Position.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_Position.addedY(-1)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
// Declares the cBlockHopperHandler class representing the handler for the Hopper block
|
||||
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockEntity.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "BlockInfo.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "Blocks/BlockStairs.h"
|
||||
#include "ChunkDef.h"
|
||||
#include "Defines.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "BlockSlab.h"
|
||||
|
||||
|
||||
|
@ -23,14 +23,15 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto BasePos = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(BasePos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Cannot be at too much daylight
|
||||
|
||||
switch (a_Chunk.GetBlock(a_Position.addedY(-1)))
|
||||
switch (a_Chunk.GetBlock(BasePos))
|
||||
{
|
||||
case E_BLOCK_GLASS:
|
||||
case E_BLOCK_CACTUS:
|
||||
|
@ -60,7 +60,8 @@ private:
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
// Needs to be placed on top of a Soulsand block:
|
||||
return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_SOULSAND);
|
||||
const auto BasePos = a_Position.addedY(-1);
|
||||
return cChunkDef::IsValidHeight(BasePos) && (a_Chunk.GetBlock(BasePos) == E_BLOCK_SOULSAND);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
class cBlockObserverHandler final :
|
||||
|
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "../Item.h"
|
||||
|
||||
|
||||
|
@ -51,9 +51,9 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if ((a_Position.y <= 0) || (a_Position.y >= cChunkDef::Height - 1))
|
||||
if (!cChunkDef::IsValidHeight(a_Position.addedY(-1)) || !cChunkDef::IsValidHeight(a_Position.addedY(1)))
|
||||
{
|
||||
return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1.
|
||||
return false; // Must be 1 away from the boundary, there will always be another portal or an obsidian between the portal block and the boundary.
|
||||
}
|
||||
|
||||
switch (a_Meta)
|
||||
|
@ -22,14 +22,15 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto PosBelow = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(PosBelow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), Block, BlockMeta);
|
||||
a_Chunk.GetBlockTypeMeta(PosBelow, Block, BlockMeta);
|
||||
|
||||
// upside down slabs
|
||||
if (cBlockSlabHandler::IsAnySlabType(Block))
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "BlockSlab.h"
|
||||
#include "BlockStairs.h"
|
||||
#include "BlockType.h"
|
||||
#include "Blocks/Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "Mixins/SolidSurfaceUnderneath.h"
|
||||
#include "../BlockInfo.h"
|
||||
#include "../Chunk.h"
|
||||
#include "ChunkDef.h"
|
||||
@ -25,9 +24,9 @@ enum ENUM_PURE
|
||||
|
||||
|
||||
class cBlockRailHandler final :
|
||||
public cClearMetaOnDrop<cBlockHandler>
|
||||
public cSolidSurfaceUnderneath<cClearMetaOnDrop<cBlockHandler>>
|
||||
{
|
||||
using Super = cClearMetaOnDrop<cBlockHandler>;
|
||||
using Super = cSolidSurfaceUnderneath<cClearMetaOnDrop<cBlockHandler>>;
|
||||
|
||||
public:
|
||||
|
||||
@ -162,26 +161,9 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
static bool CanBeSupportedBy(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||
{
|
||||
if (cBlockSlabHandler::IsAnySlabType(a_BlockType))
|
||||
{
|
||||
return (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN);
|
||||
}
|
||||
else if (cBlockStairsHandler::IsAnyStairType(a_BlockType))
|
||||
{
|
||||
return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN);
|
||||
}
|
||||
return cBlockInfo::FullyOccupiesVoxel(a_BlockType);
|
||||
}
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
|
||||
|
||||
if ((a_Position.y <= 0) || !CanBeSupportedBy(BelowBlock, BelowBlockMeta))
|
||||
if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -3,10 +3,9 @@
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "BlockType.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "Mixins/SolidSurfaceUnderneath.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "BlockSlab.h"
|
||||
#include "BlockStairs.h"
|
||||
#include "../Chunk.h"
|
||||
|
||||
|
||||
@ -14,9 +13,9 @@
|
||||
|
||||
|
||||
class cBlockRedstoneRepeaterHandler final :
|
||||
public cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>
|
||||
public cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>
|
||||
{
|
||||
using Super = cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>;
|
||||
using Super = cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>;
|
||||
|
||||
public:
|
||||
|
||||
@ -107,41 +106,6 @@ private:
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// upside down slabs
|
||||
if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
// upside down stairs
|
||||
if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
|
||||
{
|
||||
return cItem(E_ITEM_REDSTONE_REPEATER, 1, 0);
|
||||
|
@ -2,17 +2,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "BlockSlab.h"
|
||||
#include "BlockStairs.h"
|
||||
#include "../Chunk.h"
|
||||
#include "Mixins/SolidSurfaceUnderneath.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockRedstoneWireHandler final :
|
||||
public cBlockHandler
|
||||
public cSolidSurfaceUnderneath<cBlockHandler>
|
||||
{
|
||||
using Super = cBlockHandler;
|
||||
using Super = cSolidSurfaceUnderneath<cBlockHandler>;
|
||||
|
||||
public:
|
||||
|
||||
@ -20,41 +18,6 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// upside down slabs
|
||||
if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
// upside down stairs
|
||||
if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
|
||||
{
|
||||
return cItem(E_ITEM_REDSTONE_DUST, 1, 0);
|
||||
|
@ -3,15 +3,16 @@
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "../FastRandom.h"
|
||||
#include "Mixins/DirtLikeUnderneath.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockSaplingHandler final :
|
||||
public cBlockHandler
|
||||
public cDirtLikeUnderneath<cBlockHandler>
|
||||
{
|
||||
using Super = cBlockHandler;
|
||||
using Super = cDirtLikeUnderneath<cBlockHandler>;
|
||||
|
||||
public:
|
||||
|
||||
@ -29,15 +30,6 @@ private:
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return (a_Position.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_Position.addedY(-1)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void OnUpdate(
|
||||
cChunkInterface & a_ChunkInterface,
|
||||
cWorldInterface & a_WorldInterface,
|
||||
|
@ -30,12 +30,13 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto BelowPos = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(BelowPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE Type = a_Chunk.GetBlock(a_Position.addedY(-1));
|
||||
BLOCKTYPE Type = a_Chunk.GetBlock(BelowPos);
|
||||
return (Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type);
|
||||
}
|
||||
|
||||
|
@ -69,11 +69,11 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto BelowPos = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(BelowPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto BelowPos = a_Position.addedY(-1);
|
||||
auto BlockBelow = a_Chunk.GetBlock(BelowPos);
|
||||
auto MetaBelow = a_Chunk.GetMeta(BelowPos);
|
||||
return CanBeOn(BlockBelow, MetaBelow);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -5,15 +5,16 @@
|
||||
|
||||
#include "../BlockInfo.h"
|
||||
#include "BlockEntity.h"
|
||||
#include "Mixins/SolidSurfaceUnderneath.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockStandingBannerHandler final :
|
||||
public cBlockEntityHandler
|
||||
public cSolidSurfaceUnderneath<cBlockEntityHandler>
|
||||
{
|
||||
using Super = cBlockEntityHandler;
|
||||
using Super = cSolidSurfaceUnderneath<cBlockEntityHandler>;
|
||||
|
||||
public:
|
||||
|
||||
@ -29,20 +30,6 @@ public:
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return cBlockInfo::IsSolid(a_Chunk.GetBlock(a_Position.addedY(-1)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
@ -58,7 +58,8 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND);
|
||||
const auto BelowPos = a_Position.addedY(-1);
|
||||
return cChunkDef::IsValidHeight(BelowPos) && (a_Chunk.GetBlock(BelowPos) == E_BLOCK_FARMLAND);
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,12 +29,13 @@ private:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
const auto BelowPos = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(BelowPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (a_Chunk.GetBlock(a_Position.addedY(-1)))
|
||||
switch (a_Chunk.GetBlock(BelowPos))
|
||||
{
|
||||
case E_BLOCK_DIRT:
|
||||
case E_BLOCK_GRASS:
|
||||
@ -43,16 +44,16 @@ private:
|
||||
{
|
||||
static const Vector3i Coords[] =
|
||||
{
|
||||
{-1, -1, 0},
|
||||
{ 1, -1, 0},
|
||||
{ 0, -1, -1},
|
||||
{ 0, -1, 1},
|
||||
{-1, 0, 0},
|
||||
{ 1, 0, 0},
|
||||
{ 0, 0, -1},
|
||||
{ 0, 0, 1},
|
||||
} ;
|
||||
for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta))
|
||||
if (!a_Chunk.UnboundedRelGetBlock(BelowPos + Coords[i], BlockType, BlockMeta))
|
||||
{
|
||||
// Too close to the edge, cannot simulate
|
||||
return true;
|
||||
@ -90,31 +91,36 @@ private:
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
|
||||
{
|
||||
// Check the total height of the sugarcane blocks here:
|
||||
int top = a_RelPos.y + 1;
|
||||
auto top = a_RelPos.addedY(1);
|
||||
while (
|
||||
(top < cChunkDef::Height) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_SUGARCANE)
|
||||
cChunkDef::IsValidHeight(top) &&
|
||||
(a_Chunk.GetBlock(top) == E_BLOCK_SUGARCANE)
|
||||
)
|
||||
{
|
||||
++top;
|
||||
++top.y;
|
||||
}
|
||||
int bottom = a_RelPos.y - 1;
|
||||
auto bottom = a_RelPos.addedY(-1);
|
||||
while (
|
||||
(bottom > 0) &&
|
||||
(a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_SUGARCANE)
|
||||
cChunkDef::IsValidHeight(bottom) &&
|
||||
(a_Chunk.GetBlock(bottom) == E_BLOCK_SUGARCANE)
|
||||
)
|
||||
{
|
||||
--bottom;
|
||||
--bottom.y;
|
||||
}
|
||||
|
||||
// Grow by at most a_NumStages, but no more than max height:
|
||||
auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top - bottom));
|
||||
Vector3i topPos(a_RelPos.x, top, a_RelPos.z);
|
||||
auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top.y - bottom.y));
|
||||
for (int i = 0; i < toGrow; i++)
|
||||
{
|
||||
if (a_Chunk.GetBlock(topPos.addedY(i)) == E_BLOCK_AIR)
|
||||
const auto NewTop = top.addedY(i);
|
||||
if (!cChunkDef::IsValidHeight(NewTop))
|
||||
{
|
||||
a_Chunk.SetBlock(topPos.addedY(i), E_BLOCK_SUGARCANE, 0);
|
||||
return i;
|
||||
}
|
||||
|
||||
if (a_Chunk.GetBlock(NewTop) == E_BLOCK_AIR)
|
||||
{
|
||||
a_Chunk.SetBlock(NewTop, E_BLOCK_SUGARCANE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins/DirtLikeUnderneath.h"
|
||||
#include "ChunkInterface.h"
|
||||
|
||||
|
||||
@ -10,9 +11,9 @@
|
||||
|
||||
/** Handles the grass that is 1 block tall */
|
||||
class cBlockTallGrassHandler final :
|
||||
public cBlockHandler
|
||||
public cDirtLikeUnderneath<cBlockHandler>
|
||||
{
|
||||
using Super = cBlockHandler;
|
||||
using Super = cDirtLikeUnderneath<cBlockHandler>;
|
||||
|
||||
public:
|
||||
|
||||
@ -52,25 +53,11 @@ private:
|
||||
|
||||
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (a_Position.y <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_Position.addedY(-1));
|
||||
return IsBlockTypeOfDirt(BelowBlock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Growing a tall grass produces a big flower (2-block high fern or double-tall grass). */
|
||||
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
|
||||
{
|
||||
if (a_RelPos.y > (cChunkDef::Height - 2))
|
||||
const auto TopPos = a_RelPos.addedY(1);
|
||||
if (!cChunkDef::IsValidHeight(TopPos))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -83,7 +70,7 @@ private:
|
||||
default: return 0;
|
||||
}
|
||||
a_Chunk.SetBlock(a_RelPos, E_BLOCK_BIG_FLOWER, largeFlowerMeta);
|
||||
a_Chunk.SetBlock(a_RelPos.addedY(1), E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
|
||||
a_Chunk.SetBlock(TopPos, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "BlockType.h"
|
||||
#include "ChunkInterface.h"
|
||||
#include "Defines.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
@ -126,7 +126,7 @@ private:
|
||||
NIBBLETYPE NeighborBlockMeta;
|
||||
if (!a_Chunk.UnboundedRelGetBlock(NeighborRelPos, NeighborBlockType, NeighborBlockMeta))
|
||||
{
|
||||
// Neighbor in an unloaded chunk, bail out without changint this.
|
||||
// Neighbor in an unloaded chunk, bail out without changing this.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
#include "../EffectID.h"
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "Mixins.h"
|
||||
#include "Mixins/Mixins.h"
|
||||
|
||||
|
||||
|
||||
|
@ -119,15 +119,16 @@ private:
|
||||
}
|
||||
|
||||
// Check if vine above us, add its meta to MaxMeta:
|
||||
if ((a_Position.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_Position.addedY(1)) == E_BLOCK_VINES))
|
||||
const auto AbovePos = a_Position.addedY(1);
|
||||
if (cChunkDef::IsValidHeight(AbovePos) && (a_Chunk.GetBlock(AbovePos) == E_BLOCK_VINES))
|
||||
{
|
||||
MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1));
|
||||
MaxMeta |= a_Chunk.GetMeta(AbovePos);
|
||||
}
|
||||
|
||||
NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal.
|
||||
if (Common != a_CurrentMeta)
|
||||
{
|
||||
bool HasTop = (a_Position.y < (cChunkDef::Height - 1)) && IsBlockAttachable(a_Chunk.GetBlock(a_Position.addedY(1)));
|
||||
bool HasTop = cChunkDef::IsValidHeight(AbovePos) && IsBlockAttachable(a_Chunk.GetBlock(AbovePos));
|
||||
if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine.
|
||||
{
|
||||
return VINE_LOST_SUPPORT;
|
||||
|
@ -110,6 +110,6 @@ target_sources(
|
||||
BroadcastInterface.h
|
||||
ChunkInterface.h
|
||||
GetHandlerCompileTimeTemplate.h
|
||||
Mixins.h
|
||||
Mixins/Mixins.h
|
||||
WorldInterface.h
|
||||
)
|
||||
|
42
src/Blocks/Mixins/DirtLikeUnderneath.h
Normal file
42
src/Blocks/Mixins/DirtLikeUnderneath.h
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../Chunk.h"
|
||||
|
||||
/** Mixin to ensure the block has a dirt-like block underneath. */
|
||||
template <class Base>
|
||||
class cDirtLikeUnderneath :
|
||||
public Base
|
||||
{
|
||||
using Super = Base;
|
||||
public:
|
||||
|
||||
using Super::Super;
|
||||
|
||||
constexpr cDirtLikeUnderneath(BLOCKTYPE a_BlockType):
|
||||
Base(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~cDirtLikeUnderneath() = default;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto BelowPos = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(BelowPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsBlockTypeOfDirt(a_Chunk.GetBlock(BelowPos));
|
||||
}
|
||||
};
|
@ -9,7 +9,7 @@ class cBlockLadder: public cMetaRotator<cClearMetaOnDrop, ...>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Item.h"
|
||||
#include "../../Item.h"
|
||||
|
||||
|
||||
|
65
src/Blocks/Mixins/SolidSurfaceUnderneath.h
Normal file
65
src/Blocks/Mixins/SolidSurfaceUnderneath.h
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../Chunk.h"
|
||||
#include "../BlockSlab.h"
|
||||
#include "../BlockStairs.h"
|
||||
|
||||
/** Mixin to ensure the block has a solid surface underneath. */
|
||||
template <class Base>
|
||||
class cSolidSurfaceUnderneath :
|
||||
public Base
|
||||
{
|
||||
using Super = Base;
|
||||
public:
|
||||
|
||||
using Super::Super;
|
||||
|
||||
constexpr cSolidSurfaceUnderneath(BLOCKTYPE a_BlockType):
|
||||
Base(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~cSolidSurfaceUnderneath() = default;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto BelowPos = a_Position.addedY(-1);
|
||||
if (!cChunkDef::IsValidHeight(BelowPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BelowBlock;
|
||||
NIBBLETYPE BelowBlockMeta;
|
||||
a_Chunk.GetBlockTypeMeta(BelowPos, BelowBlock, BelowBlockMeta);
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// upside down slabs
|
||||
if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
// upside down stairs
|
||||
if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
|
||||
{
|
||||
return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user