diff options
Diffstat (limited to '')
52 files changed, 374 insertions, 317 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/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 4b0d7e5ec..6691f151f 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -7,7 +7,6 @@ #include "BlockPluginInterface.h" #include "BlockAir.h" #include "BlockAnvil.h" -#include "BlockBanner.h" #include "BlockBed.h" #include "BlockBigFlower.h" #include "BlockBookShelf.h" @@ -89,6 +88,7 @@ #include "BlockSnow.h" #include "BlockSponge.h" #include "BlockStairs.h" +#include "BlockStandingBanner.h" #include "BlockStems.h" #include "BlockStone.h" #include "BlockSugarCane.h" @@ -99,6 +99,7 @@ #include "BlockTripwire.h" #include "BlockTripwireHook.h" #include "BlockVines.h" +#include "BlockWallBanner.h" #include "BlockWallSign.h" #include "BlockWorkbench.h" @@ -413,7 +414,7 @@ namespace constexpr cDefaultBlockHandler BlockStainedClayHandler (E_BLOCK_STAINED_CLAY); constexpr cBlockGlassHandler BlockStainedGlassHandler (E_BLOCK_STAINED_GLASS); constexpr cBlockGlassHandler BlockStainedGlassPaneHandler (E_BLOCK_STAINED_GLASS_PANE); - constexpr cBlockBannerHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER); + constexpr cBlockStandingBannerHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER); constexpr cBlockLavaHandler BlockStationaryLavaHandler (E_BLOCK_STATIONARY_LAVA); constexpr cBlockWaterHandler BlockStationaryWaterHandler (E_BLOCK_STATIONARY_WATER); constexpr cBlockPistonHandler BlockStickyPistonHandler (E_BLOCK_STICKY_PISTON); @@ -434,7 +435,7 @@ namespace constexpr cBlockTripwireHandler BlockTripwireHandler (E_BLOCK_TRIPWIRE); constexpr cBlockTripwireHookHandler BlockTripwireHookHandler (E_BLOCK_TRIPWIRE_HOOK); constexpr cBlockVinesHandler BlockVinesHandler (E_BLOCK_VINES); - constexpr cBlockBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER); + constexpr cBlockWallBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER); constexpr cBlockWallSignHandler BlockWallsignHandler (E_BLOCK_WALLSIGN); constexpr cBlockWaterHandler BlockWaterHandler (E_BLOCK_WATER); constexpr cBlockGlazedTerracottaHandler BlockWhiteGlazedTerracottaHandler (E_BLOCK_WHITE_GLAZED_TERRACOTTA); 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.cpp b/src/Blocks/BlockPiston.cpp index 124757b44..568e2eaa5 100644 --- a/src/Blocks/BlockPiston.cpp +++ b/src/Blocks/BlockPiston.cpp @@ -48,8 +48,12 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World) BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; - a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta); - a_World.BroadcastBlockAction(a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock); + if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta)) + { + a_World.BroadcastBlockAction( + a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock + ); + } } // Client expects the server to "play" the animation before setting the final blocks @@ -60,9 +64,12 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World) { BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; - World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta); - if ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock)) + + if ( + !World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) || + ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock)) + ) { // Ensure we operate on a piston to avoid spurious behaviour // Note that the scheduled task may result in the block type of a_BlockPos changing @@ -104,17 +111,23 @@ void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld & a_World) { BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; - a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta); - a_World.BroadcastBlockAction(a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock); + if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta)) + { + a_World.BroadcastBlockAction( + a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock + ); + } } a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World) { BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; - World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta); - if ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock)) + if ( + !World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) || + ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock)) + ) { // Ensure we operate on a piston to avoid spurious behaviour // Note that the scheduled task may result in the block type of a_BlockPos changing @@ -189,19 +202,20 @@ void cBlockPistonHandler::PushBlocks( NIBBLETYPE moveMeta; for (auto & moveBlockPos : sortedBlocks) { - a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta); - - if (cBlockInfo::IsPistonBreakable(moveBlock)) - { - // Block is breakable, drop it: - a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr); - } - else + if (a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta)) { - // Not breakable, just move it - a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0); - moveBlockPos += a_PushDir; - a_World.SetBlock(moveBlockPos, moveBlock, moveMeta); + if (cBlockInfo::IsPistonBreakable(moveBlock)) + { + // Block is breakable, drop it: + a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr); + } + else + { + // Not breakable, just move it + a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0); + moveBlockPos += a_PushDir; + a_World.SetBlock(moveBlockPos, moveBlock, moveMeta); + } } } } @@ -232,7 +246,10 @@ bool cBlockPistonHandler::CanPushBlock( BLOCKTYPE currBlock; NIBBLETYPE currMeta; - a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta); + if (!a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta)) + { + return !a_RequirePushable; + } if (currBlock == E_BLOCK_AIR) { 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/BlockBanner.h b/src/Blocks/BlockStandingBanner.h index e6a159bd4..0cc7c28eb 100644 --- a/src/Blocks/BlockBanner.h +++ b/src/Blocks/BlockStandingBanner.h @@ -1,19 +1,20 @@ -// BlockBanner.h +// BlockStandingBanner.h #pragma once #include "../BlockInfo.h" #include "BlockEntity.h" +#include "Mixins/SolidSurfaceUnderneath.h" -class cBlockBannerHandler final : - public cBlockEntityHandler +class cBlockStandingBannerHandler final : + 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/BlockWallBanner.h b/src/Blocks/BlockWallBanner.h new file mode 100644 index 000000000..e0ebb8eee --- /dev/null +++ b/src/Blocks/BlockWallBanner.h @@ -0,0 +1,64 @@ + +// BlockWallBanner.h + +#pragma once + +#include "../BlockInfo.h" +#include "BlockEntity.h" + + + + + +class cBlockWallBannerHandler final : + public cBlockEntityHandler +{ + using Super = cBlockEntityHandler; + +public: + + using Super::Super; + + virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override + { + // Drops handled by the block entity: + return {}; + } + + + + + + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override + { + Vector3i Offset; + + switch (a_Meta) + { + case BLOCK_FACE_ZM: Offset = Vector3i( 0, 0, 1); break; + case BLOCK_FACE_ZP: Offset = Vector3i( 0, 0, -1); break; + case BLOCK_FACE_XM: Offset = Vector3i( 1, 0, 0); break; + case BLOCK_FACE_XP: Offset = Vector3i(-1, 0, 0); break; + default: return false; + } + + auto NeighborPos = a_Position + Offset; + BLOCKTYPE NeighborType; + if (!a_Chunk.UnboundedRelGetBlockType(NeighborPos, NeighborType)) + { + // The neighbour is not accessible (unloaded chunk), we'll allow it for now. + return true; + } + return cBlockInfo::IsSolid(NeighborType); + } + + + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override + { + UNUSED(a_Meta); + return 0; + } +} ; diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt index a7dd7b675..7e3047451 100644 --- a/src/Blocks/CMakeLists.txt +++ b/src/Blocks/CMakeLists.txt @@ -9,7 +9,6 @@ target_sources( BlockAir.h BlockAnvil.h - BlockBanner.h BlockBed.h BlockBigFlower.h BlockBookShelf.h @@ -94,6 +93,7 @@ target_sources( BlockSnow.h BlockSponge.h BlockStairs.h + BlockStandingBanner.h BlockStems.h BlockStone.h BlockSugarCane.h @@ -104,11 +104,12 @@ target_sources( BlockTripwire.h BlockTripwireHook.h BlockVines.h + BlockWallBanner.h BlockWallSign.h BlockWorkbench.h 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; + } +}; |