summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Blocks/BlockAnvil.h2
-rw-r--r--src/Blocks/BlockBed.h2
-rw-r--r--src/Blocks/BlockBigFlower.h7
-rw-r--r--src/Blocks/BlockBrewingStand.h2
-rw-r--r--src/Blocks/BlockButton.h2
-rw-r--r--src/Blocks/BlockCactus.h36
-rw-r--r--src/Blocks/BlockCarpet.h3
-rw-r--r--src/Blocks/BlockChest.h2
-rw-r--r--src/Blocks/BlockCocoaPod.h7
-rw-r--r--src/Blocks/BlockComparator.h43
-rw-r--r--src/Blocks/BlockCrops.h9
-rw-r--r--src/Blocks/BlockDeadBush.h5
-rw-r--r--src/Blocks/BlockDoor.h22
-rw-r--r--src/Blocks/BlockDropSpenser.h2
-rw-r--r--src/Blocks/BlockEnderChest.h2
-rw-r--r--src/Blocks/BlockFenceGate.h2
-rw-r--r--src/Blocks/BlockFlower.h14
-rw-r--r--src/Blocks/BlockFurnace.h2
-rw-r--r--src/Blocks/BlockGlazedTerracotta.h2
-rw-r--r--src/Blocks/BlockHopper.h2
-rw-r--r--src/Blocks/BlockJukebox.h2
-rw-r--r--src/Blocks/BlockLadder.h2
-rw-r--r--src/Blocks/BlockLever.h2
-rw-r--r--src/Blocks/BlockMushroom.h5
-rw-r--r--src/Blocks/BlockNetherWart.h3
-rw-r--r--src/Blocks/BlockObserver.h2
-rw-r--r--src/Blocks/BlockPiston.h2
-rw-r--r--src/Blocks/BlockPortal.h4
-rw-r--r--src/Blocks/BlockPressurePlate.h5
-rw-r--r--src/Blocks/BlockPumpkin.h2
-rw-r--r--src/Blocks/BlockRail.h28
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h44
-rw-r--r--src/Blocks/BlockRedstoneWire.h43
-rw-r--r--src/Blocks/BlockSapling.h14
-rw-r--r--src/Blocks/BlockSignPost.h5
-rw-r--r--src/Blocks/BlockSnow.h4
-rw-r--r--src/Blocks/BlockStairs.h2
-rw-r--r--src/Blocks/BlockStandingBanner.h19
-rw-r--r--src/Blocks/BlockStems.h3
-rw-r--r--src/Blocks/BlockSugarCane.h44
-rw-r--r--src/Blocks/BlockTallGrass.h25
-rw-r--r--src/Blocks/BlockTorch.h4
-rw-r--r--src/Blocks/BlockTrapdoor.h2
-rw-r--r--src/Blocks/BlockTripwireHook.h2
-rw-r--r--src/Blocks/BlockVines.h7
-rw-r--r--src/Blocks/CMakeLists.txt2
-rw-r--r--src/Blocks/Mixins/DirtLikeUnderneath.h42
-rw-r--r--src/Blocks/Mixins/Mixins.h (renamed from src/Blocks/Mixins.h)2
-rw-r--r--src/Blocks/Mixins/SolidSurfaceUnderneath.h65
49 files changed, 264 insertions, 290 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h
index bc031216a..eb8053af1 100644
--- a/src/Blocks/BlockAnvil.h
+++ b/src/Blocks/BlockAnvil.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../Entities/Player.h"
#include "../UI/AnvilWindow.h"
diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h
index a6b2814b9..fcf7d58a0 100644
--- a/src/Blocks/BlockBed.h
+++ b/src/Blocks/BlockBed.h
@@ -6,7 +6,7 @@
#include "BlockEntity.h"
#include "ChunkInterface.h"
#include "Entities/Player.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h
index 1b2c0d735..d8270dc6c 100644
--- a/src/Blocks/BlockBigFlower.h
+++ b/src/Blocks/BlockBigFlower.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));
}
diff --git a/src/Blocks/BlockBrewingStand.h b/src/Blocks/BlockBrewingStand.h
index d1595c690..5f41525d7 100644
--- a/src/Blocks/BlockBrewingStand.h
+++ b/src/Blocks/BlockBrewingStand.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 1a141eff3..e8affb290 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.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"
diff --git a/src/Blocks/BlockCactus.h b/src/Blocks/BlockCactus.h
index 23c4d3421..9b1461cb8 100644
--- a/src/Blocks/BlockCactus.h
+++ b/src/Blocks/BlockCactus.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);
}
diff --git a/src/Blocks/BlockCarpet.h b/src/Blocks/BlockCarpet.h
index 841e94b11..2477ee344 100644
--- a/src/Blocks/BlockCarpet.h
+++ b/src/Blocks/BlockCarpet.h
@@ -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);
}
diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h
index 119216d00..99a95e692 100644
--- a/src/Blocks/BlockChest.h
+++ b/src/Blocks/BlockChest.h
@@ -3,7 +3,7 @@
#include "../BlockArea.h"
#include "../Entities/Player.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h
index e018388c5..7906a1888 100644
--- a/src/Blocks/BlockCocoaPod.h
+++ b/src/Blocks/BlockCocoaPod.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));
}
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index 18aa2a8b9..9ce9d3dbd 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -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);
diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h
index b323ace10..59413ba08 100644
--- a/src/Blocks/BlockCrops.h
+++ b/src/Blocks/BlockCrops.h
@@ -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;
}
diff --git a/src/Blocks/BlockDeadBush.h b/src/Blocks/BlockDeadBush.h
index 080dd150c..884b6f686 100644
--- a/src/Blocks/BlockDeadBush.h
+++ b/src/Blocks/BlockDeadBush.h
@@ -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:
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 1b5c33d46..c394bda39 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -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:
diff --git a/src/Blocks/BlockDropSpenser.h b/src/Blocks/BlockDropSpenser.h
index 050adf0f1..7b18eb8da 100644
--- a/src/Blocks/BlockDropSpenser.h
+++ b/src/Blocks/BlockDropSpenser.h
@@ -5,7 +5,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockEnderChest.h b/src/Blocks/BlockEnderChest.h
index 2e0da0f17..a944ab263 100644
--- a/src/Blocks/BlockEnderChest.h
+++ b/src/Blocks/BlockEnderChest.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index f52d8df9c..75a0ded06 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../EffectID.h"
diff --git a/src/Blocks/BlockFlower.h b/src/Blocks/BlockFlower.h
index 023ba4a37..aaa532c0c 100644
--- a/src/Blocks/BlockFlower.h
+++ b/src/Blocks/BlockFlower.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);
diff --git a/src/Blocks/BlockFurnace.h b/src/Blocks/BlockFurnace.h
index 8cdc9489a..968ea398c 100644
--- a/src/Blocks/BlockFurnace.h
+++ b/src/Blocks/BlockFurnace.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockGlazedTerracotta.h b/src/Blocks/BlockGlazedTerracotta.h
index 0975f1ecd..21206ab77 100644
--- a/src/Blocks/BlockGlazedTerracotta.h
+++ b/src/Blocks/BlockGlazedTerracotta.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h
index 930f1e0bc..91ad91bff 100644
--- a/src/Blocks/BlockHopper.h
+++ b/src/Blocks/BlockHopper.h
@@ -3,7 +3,7 @@
// Declares the cBlockHopperHandler class representing the handler for the Hopper block
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockJukebox.h b/src/Blocks/BlockJukebox.h
index 970f10fc1..79475d30b 100644
--- a/src/Blocks/BlockJukebox.h
+++ b/src/Blocks/BlockJukebox.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockEntity.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index bab51b2d3..4bca19930 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -3,7 +3,7 @@
#include "BlockHandler.h"
#include "BlockInfo.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 60db4ddee..2a676ce00 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.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"
diff --git a/src/Blocks/BlockMushroom.h b/src/Blocks/BlockMushroom.h
index bed16c557..9e4378d4e 100644
--- a/src/Blocks/BlockMushroom.h
+++ b/src/Blocks/BlockMushroom.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:
diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h
index 43081d511..c0686afc6 100644
--- a/src/Blocks/BlockNetherWart.h
+++ b/src/Blocks/BlockNetherWart.h
@@ -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);
}
diff --git a/src/Blocks/BlockObserver.h b/src/Blocks/BlockObserver.h
index 13ffa4631..c2cab3068 100644
--- a/src/Blocks/BlockObserver.h
+++ b/src/Blocks/BlockObserver.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
class cBlockObserverHandler final :
diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h
index 4afeb4767..275214036 100644
--- a/src/Blocks/BlockPiston.h
+++ b/src/Blocks/BlockPiston.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../Item.h"
diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h
index 05daa9337..f4b5a50bd 100644
--- a/src/Blocks/BlockPortal.h
+++ b/src/Blocks/BlockPortal.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)
diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h
index 6d852bfc0..d69234cee 100644
--- a/src/Blocks/BlockPressurePlate.h
+++ b/src/Blocks/BlockPressurePlate.h
@@ -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))
diff --git a/src/Blocks/BlockPumpkin.h b/src/Blocks/BlockPumpkin.h
index e627eeaee..fa73db56a 100644
--- a/src/Blocks/BlockPumpkin.h
+++ b/src/Blocks/BlockPumpkin.h
@@ -1,7 +1,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h
index 4e2e6211f..dea84296f 100644
--- a/src/Blocks/BlockRail.h
+++ b/src/Blocks/BlockRail.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;
}
diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index 893691d7b..92b4b3917 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -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);
diff --git a/src/Blocks/BlockRedstoneWire.h b/src/Blocks/BlockRedstoneWire.h
index de8e59a40..edea704f4 100644
--- a/src/Blocks/BlockRedstoneWire.h
+++ b/src/Blocks/BlockRedstoneWire.h
@@ -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);
diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h
index d32b9b449..db953946a 100644
--- a/src/Blocks/BlockSapling.h
+++ b/src/Blocks/BlockSapling.h
@@ -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,
diff --git a/src/Blocks/BlockSignPost.h b/src/Blocks/BlockSignPost.h
index b96498cbd..89da77fbb 100644
--- a/src/Blocks/BlockSignPost.h
+++ b/src/Blocks/BlockSignPost.h
@@ -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);
}
diff --git a/src/Blocks/BlockSnow.h b/src/Blocks/BlockSnow.h
index f3fa87a1b..51361ce17 100644
--- a/src/Blocks/BlockSnow.h
+++ b/src/Blocks/BlockSnow.h
@@ -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);
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index 76614bb62..6c37a8464 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockStandingBanner.h b/src/Blocks/BlockStandingBanner.h
index 391b7fde7..0cc7c28eb 100644
--- a/src/Blocks/BlockStandingBanner.h
+++ b/src/Blocks/BlockStandingBanner.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);
diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h
index 11cd83967..9d598003d 100644
--- a/src/Blocks/BlockStems.h
+++ b/src/Blocks/BlockStems.h
@@ -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);
}
diff --git a/src/Blocks/BlockSugarCane.h b/src/Blocks/BlockSugarCane.h
index cffe667e5..1f6c8a8fa 100644
--- a/src/Blocks/BlockSugarCane.h
+++ b/src/Blocks/BlockSugarCane.h
@@ -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
{
diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h
index ea638c878..47ad2f93d 100644
--- a/src/Blocks/BlockTallGrass.h
+++ b/src/Blocks/BlockTallGrass.h
@@ -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;
}
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index ad69cf5eb..99f685cb6 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -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;
}
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 7f6f70e1e..3fb4f4ca3 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../EffectID.h"
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index ae553d66f..ede6ca311 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -1,7 +1,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockVines.h b/src/Blocks/BlockVines.h
index a23ba1489..edbd30f36 100644
--- a/src/Blocks/BlockVines.h
+++ b/src/Blocks/BlockVines.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;
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index 38a60d5b7..7e3047451 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -110,6 +110,6 @@ target_sources(
BroadcastInterface.h
ChunkInterface.h
GetHandlerCompileTimeTemplate.h
- Mixins.h
+ Mixins/Mixins.h
WorldInterface.h
)
diff --git a/src/Blocks/Mixins/DirtLikeUnderneath.h b/src/Blocks/Mixins/DirtLikeUnderneath.h
new file mode 100644
index 000000000..909f1601e
--- /dev/null
+++ b/src/Blocks/Mixins/DirtLikeUnderneath.h
@@ -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));
+ }
+};
diff --git a/src/Blocks/Mixins.h b/src/Blocks/Mixins/Mixins.h
index fa8985737..d9a233bad 100644
--- a/src/Blocks/Mixins.h
+++ b/src/Blocks/Mixins/Mixins.h
@@ -9,7 +9,7 @@ class cBlockLadder: public cMetaRotator<cClearMetaOnDrop, ...>
#pragma once
-#include "../Item.h"
+#include "../../Item.h"
diff --git a/src/Blocks/Mixins/SolidSurfaceUnderneath.h b/src/Blocks/Mixins/SolidSurfaceUnderneath.h
new file mode 100644
index 000000000..c54c064d6
--- /dev/null
+++ b/src/Blocks/Mixins/SolidSurfaceUnderneath.h
@@ -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;
+ }
+};