From a62b2b1be2103d7de2fd66c7304b7473e369be3c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 5 May 2021 14:25:10 +0100 Subject: Move item placement into item handlers (#5184) * Move item placement into item handlers + Add appropriate CanBeAt checks in cPlayer::PlaceBlocks, into which all placement handlers call. * Partly addresses #5157 * Fixes #4878 * Fixes #2919 * Fixes #4629 * Fixes #4239 * Fixes #4849 Co-authored-by: changyong guo Co-authored-by: Xotheus Co-authored-by: Krist Pregracke * Review fixes * Update APIDesc.lua * Rename Co-authored-by: changyong guo Co-authored-by: Xotheus Co-authored-by: Krist Pregracke --- src/Blocks/BlockAnvil.h | 22 ---- src/Blocks/BlockBanner.h | 6 +- src/Blocks/BlockBed.cpp | 16 --- src/Blocks/BlockBed.h | 5 - src/Blocks/BlockBigFlower.h | 20 ++-- src/Blocks/BlockButton.h | 46 +------ src/Blocks/BlockCactus.h | 42 +------ src/Blocks/BlockCarpet.h | 22 +--- src/Blocks/BlockChest.h | 182 ---------------------------- src/Blocks/BlockCocoaPod.h | 6 +- src/Blocks/BlockComparator.h | 6 +- src/Blocks/BlockCrops.h | 4 +- src/Blocks/BlockDeadBush.h | 8 +- src/Blocks/BlockDoor.h | 65 ++-------- src/Blocks/BlockEndPortalFrame.h | 74 ++---------- src/Blocks/BlockFire.h | 10 +- src/Blocks/BlockFlower.h | 4 +- src/Blocks/BlockFluid.h | 2 +- src/Blocks/BlockHandler.cpp | 35 +----- src/Blocks/BlockHandler.h | 34 +----- src/Blocks/BlockHopper.h | 37 +----- src/Blocks/BlockLadder.h | 106 +++-------------- src/Blocks/BlockLever.h | 53 ++------- src/Blocks/BlockLilypad.h | 4 +- src/Blocks/BlockMushroom.h | 6 +- src/Blocks/BlockNetherWart.h | 4 +- src/Blocks/BlockPlanks.h | 18 --- src/Blocks/BlockPortal.h | 34 +----- src/Blocks/BlockPressurePlate.h | 9 +- src/Blocks/BlockQuartz.h | 60 ---------- src/Blocks/BlockRail.h | 237 +++++++++++++++---------------------- src/Blocks/BlockRedstone.h | 6 +- src/Blocks/BlockRedstoneRepeater.h | 6 +- src/Blocks/BlockSapling.h | 4 +- src/Blocks/BlockSideways.h | 60 +--------- src/Blocks/BlockSignPost.h | 23 +--- src/Blocks/BlockSlab.h | 87 +++----------- src/Blocks/BlockSnow.h | 61 ++-------- src/Blocks/BlockStairs.h | 72 +---------- src/Blocks/BlockStems.h | 4 +- src/Blocks/BlockSugarcane.h | 8 +- src/Blocks/BlockTallGrass.h | 8 +- src/Blocks/BlockTorch.h | 120 +++---------------- src/Blocks/BlockTrapdoor.h | 68 ----------- src/Blocks/BlockTripwireHook.h | 52 +------- src/Blocks/BlockVine.h | 115 ++++++++---------- src/Blocks/BlockWallSign.h | 25 +--- src/Blocks/Mixins.h | 70 ++--------- src/Blocks/WorldInterface.h | 4 +- 49 files changed, 342 insertions(+), 1628 deletions(-) (limited to 'src/Blocks') diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h index 5746c936b..bc031216a 100644 --- a/src/Blocks/BlockAnvil.h +++ b/src/Blocks/BlockAnvil.h @@ -48,28 +48,6 @@ private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta)) - { - return false; - } - - a_BlockMeta = a_BlockMeta | static_cast(a_Player.GetEquippedItem().m_ItemDamage << 2); - return true; - } - - - - - virtual bool IsUseable() const override { return true; diff --git a/src/Blocks/BlockBanner.h b/src/Blocks/BlockBanner.h index cdcdfc179..e6a159bd4 100644 --- a/src/Blocks/BlockBanner.h +++ b/src/Blocks/BlockBanner.h @@ -29,14 +29,14 @@ public: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y < 1) + if (a_Position.y < 1) { return false; } - return cBlockInfo::IsSolid(a_Chunk.GetBlock(a_RelPos.addedY(-1))); + return cBlockInfo::IsSolid(a_Chunk.GetBlock(a_Position.addedY(-1))); } diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index 37c57b6b3..728c9d2b7 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -9,7 +9,6 @@ #include "../World.h" #include "../BoundingBox.h" #include "../Mobs/Monster.h" -#include "../BlockEntities/BedEntity.h" @@ -158,21 +157,6 @@ bool cBlockBedHandler::OnUse( -void cBlockBedHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange) const -{ - a_Player.GetWorld()->DoWithBlockEntityAt(a_BlockChange.GetAbsolutePos(), [&a_Player](cBlockEntity & a_BlockEntity) - { - ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_BED); - - static_cast(a_BlockEntity).SetColor(a_Player.GetEquippedItem().m_ItemDamage); - return false; - }); -} - - - - - cItems cBlockBedHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { // Drops handled by the block entity: diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h index 7da6740bd..d9f37b365 100644 --- a/src/Blocks/BlockBed.h +++ b/src/Blocks/BlockBed.h @@ -91,11 +91,6 @@ private: virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * a_Tool) const override; - virtual void OnPlacedByPlayer( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, - const sSetBlock & a_BlockChange - ) const override; - diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h index c21e411f3..6112329e9 100644 --- a/src/Blocks/BlockBigFlower.h +++ b/src/Blocks/BlockBigFlower.h @@ -20,14 +20,14 @@ public: private: - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { if (IsMetaTopPart(a_Meta)) { BLOCKTYPE BottomType; if ( - (a_Pos.y < 1) || - !a_ChunkInterface.GetBlockTypeMeta(a_Pos - Vector3i(0, 1, 0), BottomType, a_Meta) || + (a_Position.y < 1) || + !a_World.GetBlockTypeMeta(a_Position - Vector3i(0, 1, 0), BottomType, a_Meta) || (BottomType != E_BLOCK_BIG_FLOWER) ) { @@ -98,17 +98,13 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) - { - return false; - } - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BlockType, BlockMeta); + // CanBeAt is also called on placement, so the top part can't check for the bottom part. + // Both parts can only that they're rooted in grass. - return IsBlockTypeOfDirt(BlockType) || ((BlockType == E_BLOCK_BIG_FLOWER) && !IsMetaTopPart(BlockMeta)); + const auto RootPosition = a_Position.addedY(IsMetaTopPart(a_Meta) ? -2 : -1); + return (RootPosition.y >= 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition)); } diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h index 0c942cb49..896fd58d6 100644 --- a/src/Blocks/BlockButton.h +++ b/src/Blocks/BlockButton.h @@ -101,47 +101,6 @@ private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); - return true; - } - - - - - - /** Converts the block face of the neighbor to which the button is attached, to the block meta for this button. */ - inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) - { - switch (a_BlockFace) - { - case BLOCK_FACE_YP: return 0x5; - case BLOCK_FACE_ZM: return 0x4; - case BLOCK_FACE_ZP: return 0x3; - case BLOCK_FACE_XM: return 0x2; - case BLOCK_FACE_XP: return 0x1; - case BLOCK_FACE_YM: return 0x0; - case BLOCK_FACE_NONE: - { - break; - } - } - UNREACHABLE("Unsupported block face"); - } - - - - - /** Converts the block meta of this button into a block face of the neighbor to which the button is attached. */ inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { @@ -165,10 +124,9 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - auto Meta = a_Chunk.GetMeta(a_RelPos); - auto SupportRelPos = AddFaceDirection(a_RelPos, BlockMetaDataToBlockFace(Meta), true); + auto SupportRelPos = AddFaceDirection(a_Position, BlockMetaDataToBlockFace(a_Meta), true); if (!cChunkDef::IsValidHeight(SupportRelPos.y)) { return false; diff --git a/src/Blocks/BlockCactus.h b/src/Blocks/BlockCactus.h index 2e7cc7db2..23c4d3421 100644 --- a/src/Blocks/BlockCactus.h +++ b/src/Blocks/BlockCactus.h @@ -18,47 +18,13 @@ public: private: - /** Called before a cactus block is placed by a player, overrides cItemHandler::GetPlacementBlockTypeMeta(). - Calls CanBeAt function to determine if a cactus block can be placed on a given block. */ - bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if ( - a_Player.GetWorld()->DoWithChunkAt(a_PlacedBlockPos, - [this, a_PlacedBlockPos, &a_ChunkInterface](cChunk & a_Chunk) - { - auto RelPos = cChunkDef::AbsoluteToRelative(a_PlacedBlockPos); - return CanBeAt(a_ChunkInterface, RelPos, a_Chunk); - } - )) - { - a_BlockType = m_BlockType; - // Setting a_BlockMeta to meta copied from the lowest 4 bits of the player's equipped item's damage value. - NIBBLETYPE Meta = static_cast(a_Player.GetEquippedItem().m_ItemDamage); - a_BlockMeta = Meta & 0x0f; - return true; - } - - return false; - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override - { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } - BLOCKTYPE Surface = a_Chunk.GetBlock(a_RelPos.addedY(-1)); + BLOCKTYPE Surface = a_Chunk.GetBlock(a_Position.addedY(-1)); if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS)) { // Cactus can only be placed on sand and itself @@ -78,7 +44,7 @@ private: BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if ( - a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[i], BlockType, BlockMeta) && + a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta) && ( cBlockInfo::IsSolid(BlockType) || (BlockType == E_BLOCK_LAVA) || diff --git a/src/Blocks/BlockCarpet.h b/src/Blocks/BlockCarpet.h index d4c172810..841e94b11 100644 --- a/src/Blocks/BlockCarpet.h +++ b/src/Blocks/BlockCarpet.h @@ -25,27 +25,9 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - a_BlockType = m_BlockType; - a_BlockMeta = a_Player.GetEquippedItem().m_ItemDamage & 0x0f; - return true; - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override - { - return (a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) != E_BLOCK_AIR); + return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) != E_BLOCK_AIR); } diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h index 88476c82d..119216d00 100644 --- a/src/Blocks/BlockChest.h +++ b/src/Blocks/BlockChest.h @@ -18,184 +18,6 @@ public: using Super::Super; - /** Translates player yaw when placing a chest into the chest block metadata. Valid for single chests only */ - static NIBBLETYPE PlayerYawToMetaData(double a_Yaw) - { - a_Yaw += 90 + 45; // So its not aligned with axis - - if (a_Yaw > 360.f) - { - a_Yaw -= 360.f; - } - if ((a_Yaw >= 0.f) && (a_Yaw < 90.f)) - { - return 0x04; - } - else if ((a_Yaw >= 180) && (a_Yaw < 270)) - { - return 0x05; - } - else if ((a_Yaw >= 90) && (a_Yaw < 180)) - { - return 0x02; - } - else - { - return 0x03; - } - } - -private: - - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - // Cannot place right next to double-chest: - if (!CanBeAt(a_ChunkInterface, a_PlacedBlockPos)) - { - // Yup, cannot form a triple-chest, refuse: - return false; - } - - // Try to read double-chest information: - cBlockArea Area; - if (!Area.Read(a_ChunkInterface, a_PlacedBlockPos - Vector3i(1, 0, 1), a_PlacedBlockPos + Vector3i(1, 0, 1))) - { - return false; - } - - // Get meta as if this was a single-chest: - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta)) - { - return false; - } - - // Check if this forms a doublechest, if so, need to adjust the meta: - double yaw = a_Player.GetYaw(); - if ( - (Area.GetRelBlockType(0, 0, 1) == m_BlockType) || - (Area.GetRelBlockType(2, 0, 1) == m_BlockType) - ) - { - a_BlockMeta = ((yaw >= -90) && (yaw < 90)) ? 2 : 3; - return true; - } - if ( - (Area.GetRelBlockType(1, 0, 0) == m_BlockType) || - (Area.GetRelBlockType(1, 0, 2) == m_BlockType) - ) - { - a_BlockMeta = (yaw < 0) ? 4 : 5; - return true; - } - - - return true; - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override - { - auto BlockPos = a_Chunk.RelativeToAbsolute(a_RelPos); - return CanBeAt(a_ChunkInterface, BlockPos); - } - - - - - - bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) const - { - cBlockArea Area; - if (!Area.Read(a_ChunkInterface, a_BlockPos - Vector3i(2, 0, 2), a_BlockPos + Vector3i(2, 0, 2))) - { - // Cannot read the surroundings, probably at the edge of loaded chunks. Disallow. - return false; - } - - int NumChestNeighbors = 0; - if (Area.GetRelBlockType(1, 0, 2) == m_BlockType) - { - if ( - (Area.GetRelBlockType(0, 0, 2) == m_BlockType) || - (Area.GetRelBlockType(1, 0, 1) == m_BlockType) || - (Area.GetRelBlockType(1, 0, 3) == m_BlockType) - ) - { - // Already a doublechest neighbor, disallow: - return false; - } - NumChestNeighbors += 1; - } - if (Area.GetRelBlockType(3, 0, 2) == m_BlockType) - { - if ( - (Area.GetRelBlockType(4, 0, 2) == m_BlockType) || - (Area.GetRelBlockType(3, 0, 1) == m_BlockType) || - (Area.GetRelBlockType(3, 0, 3) == m_BlockType) - ) - { - // Already a doublechest neighbor, disallow: - return false; - } - NumChestNeighbors += 1; - } - if (Area.GetRelBlockType(2, 0, 1) == m_BlockType) - { - if ( - (Area.GetRelBlockType(2, 0, 0) == m_BlockType) || - (Area.GetRelBlockType(1, 0, 1) == m_BlockType) || - (Area.GetRelBlockType(3, 0, 1) == m_BlockType) - ) - { - // Already a doublechest neighbor, disallow: - return false; - } - NumChestNeighbors += 1; - } - if (Area.GetRelBlockType(2, 0, 3) == m_BlockType) - { - if ( - (Area.GetRelBlockType(2, 0, 4) == m_BlockType) || - (Area.GetRelBlockType(1, 0, 3) == m_BlockType) || - (Area.GetRelBlockType(3, 0, 3) == m_BlockType) - ) - { - // Already a doublechest neighbor, disallow: - return false; - } - NumChestNeighbors += 1; - } - return (NumChestNeighbors < 2); - } - - - - - - /** If there's a chest in the a_Area in the specified coords, modifies its meta to a_NewMeta and returns true. */ - bool CheckAndAdjustNeighbor(cChunkInterface & a_ChunkInterface, const cBlockArea & a_Area, int a_RelX, int a_RelZ, NIBBLETYPE a_NewMeta) const - { - if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != m_BlockType) - { - return false; - } - a_ChunkInterface.SetBlockMeta(a_Area.GetOriginX() + a_RelX, a_Area.GetOriginY(), a_Area.GetOriginZ() + a_RelZ, a_NewMeta); - return true; - } - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { @@ -203,7 +25,3 @@ private: return 13; } } ; - - - - diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h index 2df3a4408..e018388c5 100644 --- a/src/Blocks/BlockCocoaPod.h +++ b/src/Blocks/BlockCocoaPod.h @@ -36,11 +36,11 @@ public: private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // Check that we're attached to a jungle log block: - eBlockFace BlockFace = MetaToBlockFace(a_Chunk.GetMeta(a_RelPos)); - auto LogPos = AddFaceDirection(a_RelPos, BlockFace, true); + eBlockFace BlockFace = MetaToBlockFace(a_Meta); + auto LogPos = AddFaceDirection(a_Position, BlockFace, true); BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta); diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h index 0eb03be86..e58b386c3 100644 --- a/src/Blocks/BlockComparator.h +++ b/src/Blocks/BlockComparator.h @@ -152,16 +152,16 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } BLOCKTYPE BelowBlock; NIBBLETYPE BelowBlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BelowBlock, BelowBlockMeta); + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta); if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) { diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h index 9a79f6ac0..90a5badc9 100644 --- a/src/Blocks/BlockCrops.h +++ b/src/Blocks/BlockCrops.h @@ -116,9 +116,9 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - return ((a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_FARMLAND)); + return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND); } diff --git a/src/Blocks/BlockDeadBush.h b/src/Blocks/BlockDeadBush.h index ba206baf8..080dd150c 100644 --- a/src/Blocks/BlockDeadBush.h +++ b/src/Blocks/BlockDeadBush.h @@ -18,7 +18,7 @@ public: private: - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } @@ -27,14 +27,14 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } - BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelPos.addedY(-1)); + BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_Position.addedY(-1)); switch (BelowBlock) { case E_BLOCK_CLAY: diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h index c6d4a7b9a..1b5c33d46 100644 --- a/src/Blocks/BlockDoor.h +++ b/src/Blocks/BlockDoor.h @@ -11,6 +11,8 @@ + + class cBlockDoorHandler final : public cYawRotator { @@ -43,25 +45,6 @@ public: } } - static bool CanReplaceBlock(BLOCKTYPE a_BlockType) - { - switch (a_BlockType) - { - case E_BLOCK_AIR: - case E_BLOCK_TALL_GRASS: - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_LAVA: - case E_BLOCK_STATIONARY_LAVA: - case E_BLOCK_SNOW: - case E_BLOCK_FIRE: - { - return true; - } - } - return false; - } - /** Returns a vector pointing one block in the direction the door is facing (where the outside is). */ inline static Vector3i GetRelativeDirectionToOutside(NIBBLETYPE a_BlockMeta) { @@ -167,38 +150,6 @@ private: virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override; virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override; virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override; - - - - - - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - // If clicking a bottom face, place the door one block lower: - auto PlacedPos = a_PlacedBlockPos; - if (a_ClickedBlockFace == BLOCK_FACE_BOTTOM) - { - PlacedPos.y--; - } - - if ( - !CanReplaceBlock(a_ChunkInterface.GetBlock(PlacedPos)) || - !CanReplaceBlock(a_ChunkInterface.GetBlock(PlacedPos.addedY(1))) - ) - { - return false; - } - - return Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, PlacedPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta); - } - virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override; @@ -237,9 +188,17 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - return ((a_RelPos.y > 0) && CanBeOn(a_Chunk.GetBlock(a_RelPos.addedY(-1)), a_Chunk.GetMeta(a_RelPos.addedY(-1)))); + // 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. + + 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); } diff --git a/src/Blocks/BlockEndPortalFrame.h b/src/Blocks/BlockEndPortalFrame.h index 0b5e84da2..68e6e09fe 100644 --- a/src/Blocks/BlockEndPortalFrame.h +++ b/src/Blocks/BlockEndPortalFrame.h @@ -8,19 +8,19 @@ class cBlockEndPortalFrameHandler final : - public cMetaRotator { - using Super = cMetaRotator< + using Super = cYawRotator< cBlockHandler, 0x03, - E_META_END_PORTAL_FRAME_ZM, - E_META_END_PORTAL_FRAME_XP, E_META_END_PORTAL_FRAME_ZP, - E_META_END_PORTAL_FRAME_XM + E_META_END_PORTAL_FRAME_XM, + E_META_END_PORTAL_FRAME_ZM, + E_META_END_PORTAL_FRAME_XP >; public: @@ -29,54 +29,6 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - a_BlockMeta = YawToMetaData(a_Player.GetYaw()); - return true; - } - - - - - - inline static NIBBLETYPE YawToMetaData(double a_Rotation) - { - a_Rotation += 90 + 45; // So its not aligned with axis - if (a_Rotation > 360) - { - a_Rotation -= 360; - } - - if ((a_Rotation >= 0) && (a_Rotation < 90)) - { - return E_META_END_PORTAL_FRAME_XM; - } - else if ((a_Rotation >= 180) && (a_Rotation < 270)) - { - return E_META_END_PORTAL_FRAME_XP; - } - else if ((a_Rotation >= 90) && (a_Rotation < 180)) - { - return E_META_END_PORTAL_FRAME_ZM; - } - else - { - return E_META_END_PORTAL_FRAME_ZP; - } - } - - - - - virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const override { // E_META_END_PORTAL_FRAME_EYE is the bit which signifies the eye of ender is in it. @@ -237,16 +189,6 @@ private: - virtual bool IsClickedThrough(void) const override - { - // TODO: Colision - return true; - } - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockFire.h b/src/Blocks/BlockFire.h index 0f13db71b..a0f5e9a69 100644 --- a/src/Blocks/BlockFire.h +++ b/src/Blocks/BlockFire.h @@ -65,14 +65,6 @@ private: } - - - - virtual bool IsClickedThrough(void) const override - { - return true; - } - /** Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding */ static int FindObsidianCeiling(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, int MaxY = 0) @@ -256,7 +248,7 @@ private: return (FoundFrameZP && FoundFrameZM); } - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } diff --git a/src/Blocks/BlockFlower.h b/src/Blocks/BlockFlower.h index 17cb529cb..023ba4a37 100644 --- a/src/Blocks/BlockFlower.h +++ b/src/Blocks/BlockFlower.h @@ -28,9 +28,9 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - return ((a_RelPos.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelPos.addedY(-1)))); + return (a_Position.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_Position.addedY(-1))); } diff --git a/src/Blocks/BlockFluid.h b/src/Blocks/BlockFluid.h index cdcf49299..b39476c1d 100644 --- a/src/Blocks/BlockFluid.h +++ b/src/Blocks/BlockFluid.h @@ -32,7 +32,7 @@ private: - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 068ab998d..819289e14 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -456,24 +456,6 @@ namespace //////////////////////////////////////////////////////////////////////////////// // cBlockHandler: -bool cBlockHandler::GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - const Vector3i a_ClickedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta -) const -{ - // By default, all blocks can be placed and the meta is copied over from the item's damage value: - a_BlockType = m_BlockType; - a_BlockMeta = static_cast(a_Player.GetEquippedItem().m_ItemDamage & 0x0f); - return true; -} - - - - - void cBlockHandler::OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, @@ -490,7 +472,7 @@ void cBlockHandler::OnUpdate( void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const { - if (a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { return CanBeAt(a_ChunkInterface, cChunkDef::AbsoluteToRelative(a_BlockPos), a_Chunk); })) + if (a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { return CanBeAt(a_Chunk, cChunkDef::AbsoluteToRelative(a_BlockPos), a_Chunk.GetMeta(cChunkDef::AbsoluteToRelative(a_BlockPos))); })) { return; } @@ -528,7 +510,7 @@ cItems cBlockHandler::ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * con -bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const +bool cBlockHandler::CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const { return true; } @@ -546,18 +528,9 @@ bool cBlockHandler::IsUseable() const -bool cBlockHandler::IsClickedThrough(void) const -{ - return false; -} - - - - - -bool cBlockHandler::DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const +bool cBlockHandler::DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const { - return (m_BlockType == E_BLOCK_AIR); + return m_BlockType == E_BLOCK_AIR; } diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index da067fd63..c0e9d3a3d 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -14,6 +14,7 @@ class cPlayer; class cChunk; class cBlockPluginInterface; class cChunkInterface; +class cWorld; class cWorldInterface; class cItems; @@ -45,22 +46,6 @@ public: blocktype of the minus-X neighbor, the positive-X neighbor, etc. */ virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const; - /** Called before a block is placed into a world by player, by cItemHandler::GetPlacementBlockTypeMeta(). - The handler should return true to allow placement, false to refuse. - a_PlacedBlockPos is the coords of the block being placed - a_ClickedBlockFace is the face of the neighbor block clicked by the client to place this block. - a_CursorPos is the position of the cursor within the neighbor's face - The descendant handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block. - The default handler uses the stored block type and meta copied from the lowest 4 bits of the player's equipped item's damage value. */ - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const; - /** Called by cWorld::SetBlock() after the block has been set */ virtual void OnPlaced( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, @@ -68,11 +53,6 @@ public: BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) const {} - /** Called by cPlayer::PlaceBlocks() for each block after it has been set to the world. Called after OnPlaced(). */ - virtual void OnPlacedByPlayer( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange - ) const {} - /** Called after a block gets broken (replaced with air), by natural means. The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta. By default notifies all direct neighbors via their OnNeighborChanged() callbacks. @@ -142,11 +122,7 @@ public: virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * a_Tool = nullptr) const; /** Checks if the block can stay at the specified relative coords in the chunk */ - virtual bool CanBeAt( - cChunkInterface & a_ChunkInterface, - const Vector3i a_RelPos, - const cChunk & a_Chunk - ) const; + virtual bool CanBeAt(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) const; /** Checks whether the block has an effect on growing the plant */ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const { return false; } @@ -155,16 +131,12 @@ public: If it returns true, OnUse() is called */ virtual bool IsUseable(void) const; - /** Indicates whether the client will click through this block. - For example digging a fire will hit the block below the fire so fire is clicked through. */ - virtual bool IsClickedThrough(void) const; - /** Checks if the player can build "inside" this block. For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision @param a_Pos Position of the block @param a_Player Player trying to build on the block @param a_Meta Meta value of the block currently at a_Pos */ - virtual bool DoesIgnoreBuildCollision(cChunkInterface & ChunkInterface, const Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const; + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, Vector3i a_Position, NIBBLETYPE a_Meta, eBlockFace a_ClickedBlockFace, bool a_ClickedDirectly) const; /** Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the block. Coords in a_RelPosition are guaranteed to be in the [0..1] range. */ diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h index 915a8d8d5..930f1e0bc 100644 --- a/src/Blocks/BlockHopper.h +++ b/src/Blocks/BlockHopper.h @@ -8,9 +8,9 @@ class cBlockHopperHandler final : - public cPitchYawRotator> + public cClearMetaOnDrop> { - using Super = cPitchYawRotator>; + using Super = cClearMetaOnDrop>; public: @@ -18,42 +18,9 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - - // Convert the blockface into meta: - switch (a_ClickedBlockFace) - { - case BLOCK_FACE_BOTTOM: a_BlockMeta = E_META_HOPPER_FACING_YM; break; - case BLOCK_FACE_TOP: a_BlockMeta = E_META_HOPPER_FACING_YM; break; - case BLOCK_FACE_EAST: a_BlockMeta = E_META_HOPPER_FACING_XM; break; - case BLOCK_FACE_NORTH: a_BlockMeta = E_META_HOPPER_FACING_ZP; break; - case BLOCK_FACE_SOUTH: a_BlockMeta = E_META_HOPPER_FACING_ZM; break; - case BLOCK_FACE_WEST: a_BlockMeta = E_META_HOPPER_FACING_XP; break; - case BLOCK_FACE_NONE: a_BlockMeta = E_META_HOPPER_UNATTACHED; break; - } - return true; - } - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; - - - - diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h index b4e8294b6..06ef2b01c 100644 --- a/src/Blocks/BlockLadder.h +++ b/src/Blocks/BlockLadder.h @@ -2,6 +2,7 @@ #pragma once #include "BlockHandler.h" +#include "BlockInfo.h" #include "Mixins.h" @@ -17,58 +18,23 @@ public: using Super::Super; -private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override + /** Returns true if the ladder will be supported by the block through the given blockface. */ + static bool CanBePlacedOn(const BLOCKTYPE a_BlockType, const eBlockFace a_BlockFace) { - // Try finding a suitable neighbor block face for the ladder; start with the given one. - if (!LadderCanBePlacedAt(a_ChunkInterface, a_PlacedBlockPos, a_ClickedBlockFace)) + if ( + (a_BlockFace == BLOCK_FACE_NONE) || + (a_BlockFace == BLOCK_FACE_BOTTOM) || + (a_BlockFace == BLOCK_FACE_TOP) + ) { - a_ClickedBlockFace = FindSuitableBlockFace(a_ChunkInterface, a_PlacedBlockPos); - if (a_ClickedBlockFace == BLOCK_FACE_NONE) - { - return false; - } + return false; } - a_BlockType = m_BlockType; - a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); - return true; - } - - - - - - /** Converts the block face of the neighbor to which the ladder is attached to the ladder block's meta. */ - static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) - { - switch (a_NeighborBlockFace) - { - case BLOCK_FACE_ZM: return 0x2; - case BLOCK_FACE_ZP: return 0x3; - case BLOCK_FACE_XM: return 0x4; - case BLOCK_FACE_XP: return 0x5; - case BLOCK_FACE_NONE: - case BLOCK_FACE_YM: - case BLOCK_FACE_YP: - { - return 0x2; - } - } - UNREACHABLE("Unsupported neighbor block face"); + return cBlockInfo::IsSolid(a_BlockType); } - - - +private: /** Converts the ladder block's meta to the block face of the neighbor to which the ladder is attached. */ static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) @@ -87,51 +53,13 @@ private: - /** Finds a suitable block face value for the Ladder. - The returned value is the block face of the neighbor of the specified block to which a ladder at a_LadderPos can be attached. - Returns BLOCK_FACE_NONE if no valid location is found */ - static eBlockFace FindSuitableBlockFace(cChunkInterface & a_ChunkInterface, const Vector3i a_LadderPos) - { - for (int FaceInt = BLOCK_FACE_ZM; FaceInt <= BLOCK_FACE_XP; FaceInt++) - { - eBlockFace Face = static_cast(FaceInt); - if (LadderCanBePlacedAt(a_ChunkInterface, a_LadderPos, Face)) - { - return Face; - } - } - return BLOCK_FACE_NONE; - } - - - - - - /** Returns true if the ladder in the specified position will be supported by its neghbor through the specified neighbor's blockface. */ - static bool LadderCanBePlacedAt(cChunkInterface & a_ChunkInterface, const Vector3i a_LadderPos, eBlockFace a_NeighborBlockFace) - { - if ( - (a_NeighborBlockFace == BLOCK_FACE_NONE) || - (a_NeighborBlockFace == BLOCK_FACE_BOTTOM) || - (a_NeighborBlockFace == BLOCK_FACE_TOP) - ) - { - return false; - } - - auto NeighborPos = AddFaceDirection(a_LadderPos, a_NeighborBlockFace, true); - return cBlockInfo::IsSolid(a_ChunkInterface.GetBlock(NeighborPos)); - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - auto NeighborBlockFace = MetaDataToBlockFace(a_Chunk.GetMeta(a_RelPos)); - auto LadderAbsPos = a_Chunk.RelativeToAbsolute(a_RelPos); - return LadderCanBePlacedAt(a_ChunkInterface, LadderAbsPos, NeighborBlockFace); + auto Face = MetaDataToBlockFace(a_Meta); + auto NeighborRelPos = AddFaceDirection(a_Position, Face, true); + BLOCKTYPE NeighborBlockType; + a_Chunk.UnboundedRelGetBlockType(NeighborRelPos, NeighborBlockType); + return CanBePlacedOn(NeighborBlockType, Face); } diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h index ee5e99b9c..ddb459fbe 100644 --- a/src/Blocks/BlockLever.h +++ b/src/Blocks/BlockLever.h @@ -64,45 +64,6 @@ private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - a_BlockMeta = LeverDirectionToMetaData(a_ClickedBlockFace); - return true; - } - - - - - - /** Converts the block face of the neighbor to which the lever is attached to the lever block's meta. */ - inline static NIBBLETYPE LeverDirectionToMetaData(eBlockFace a_Dir) - { - // Determine lever direction: - switch (a_Dir) - { - case BLOCK_FACE_YP: return 0x6; - case BLOCK_FACE_XP: return 0x1; - case BLOCK_FACE_XM: return 0x2; - case BLOCK_FACE_ZP: return 0x3; - case BLOCK_FACE_ZM: return 0x4; - case BLOCK_FACE_YM: return 0x0; - case BLOCK_FACE_NONE: return 0x6; - } - UNREACHABLE("Unsupported block face"); - } - - - - - /** Converts the leve block's meta to the block face of the neighbor to which the lever is attached. */ inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { @@ -128,18 +89,18 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // Find the type of block the lever is attached to: - auto Meta = a_Chunk.GetMeta(a_RelPos); - auto NeighborFace = BlockMetaDataToBlockFace(Meta); - auto NeighborPos = AddFaceDirection(a_RelPos, NeighborFace, true); + auto NeighborFace = BlockMetaDataToBlockFace(a_Meta); + auto NeighborPos = AddFaceDirection(a_Position, NeighborFace, true); if (!cChunkDef::IsValidHeight(NeighborPos.y)) { return false; } BLOCKTYPE NeighborBlockType; - if (!a_Chunk.UnboundedRelGetBlock(NeighborPos, NeighborBlockType, Meta)) + NIBBLETYPE NeighborMeta; + if (!a_Chunk.UnboundedRelGetBlock(NeighborPos, NeighborBlockType, NeighborMeta)) { return false; } @@ -152,8 +113,8 @@ private: else if (cBlockSlabHandler::IsAnySlabType(NeighborBlockType)) { return ( - (((Meta & 0x08) == 0x08) && (NeighborFace == BLOCK_FACE_TOP)) || - (((Meta & 0x08) == 0) && (NeighborFace == BLOCK_FACE_BOTTOM)) + (((NeighborMeta & 0x08) == 0x08) && (NeighborFace == BLOCK_FACE_TOP)) || + (((NeighborMeta & 0x08) == 0) && (NeighborFace == BLOCK_FACE_BOTTOM)) ); } diff --git a/src/Blocks/BlockLilypad.h b/src/Blocks/BlockLilypad.h index 165e2d310..6d25a0e2d 100644 --- a/src/Blocks/BlockLilypad.h +++ b/src/Blocks/BlockLilypad.h @@ -28,9 +28,9 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - auto UnderPos = a_RelPos.addedY(-1); + auto UnderPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(UnderPos.y)) { return false; diff --git a/src/Blocks/BlockMushroom.h b/src/Blocks/BlockMushroom.h index bad4fc247..bed16c557 100644 --- a/src/Blocks/BlockMushroom.h +++ b/src/Blocks/BlockMushroom.h @@ -21,16 +21,16 @@ private: // TODO: Add Mushroom Spread - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } // TODO: Cannot be at too much daylight - switch (a_Chunk.GetBlock(a_RelPos.addedY(-1))) + switch (a_Chunk.GetBlock(a_Position.addedY(-1))) { case E_BLOCK_GLASS: case E_BLOCK_CACTUS: diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h index 4afdaffa2..43081d511 100644 --- a/src/Blocks/BlockNetherWart.h +++ b/src/Blocks/BlockNetherWart.h @@ -57,10 +57,10 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + 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_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_SOULSAND)); + return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_SOULSAND); } diff --git a/src/Blocks/BlockPlanks.h b/src/Blocks/BlockPlanks.h index f095f9ea3..d6e79b3c0 100644 --- a/src/Blocks/BlockPlanks.h +++ b/src/Blocks/BlockPlanks.h @@ -18,24 +18,6 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - a_BlockMeta = static_cast(a_Player.GetEquippedItem().m_ItemDamage); - return true; - } - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { switch (a_Meta) diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h index cc7fa3a1f..05daa9337 100644 --- a/src/Blocks/BlockPortal.h +++ b/src/Blocks/BlockPortal.h @@ -18,28 +18,6 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - // We set meta to zero so Cuberite doesn't stop a Creative-mode player from building custom portal shapes - // CanBeAt doesn't do anything if meta is zero - // We set to zero because the client sends meta = 1 or 2 to the server (it calculates rotation itself) - - a_BlockType = m_BlockType; - a_BlockMeta = 0; - return true; - } - - - - - virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // No pickups @@ -71,14 +49,14 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if ((a_RelPos.y <= 0) || (a_RelPos.y >= cChunkDef::Height - 1)) + if ((a_Position.y <= 0) || (a_Position.y >= cChunkDef::Height - 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; // 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. } - switch (a_Chunk.GetMeta(a_RelPos)) + switch (a_Meta) { case 0x1: { @@ -95,7 +73,7 @@ private: for (const auto & Direction : PortalCheck) { BLOCKTYPE Block; - a_Chunk.UnboundedRelGetBlockType(a_RelPos + Direction, Block); + a_Chunk.UnboundedRelGetBlockType(a_Position + Direction, Block); if ((Block != E_BLOCK_NETHER_PORTAL) && (Block != E_BLOCK_OBSIDIAN)) { return false; @@ -118,7 +96,7 @@ private: for (const auto & Direction : PortalCheck) { BLOCKTYPE Block; - a_Chunk.UnboundedRelGetBlockType(a_RelPos + Direction, Block); + a_Chunk.UnboundedRelGetBlockType(a_Position + Direction, Block); if ((Block != E_BLOCK_NETHER_PORTAL) && (Block != E_BLOCK_OBSIDIAN)) { return false; diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h index c9a72a751..d2f05b2e7 100644 --- a/src/Blocks/BlockPressurePlate.h +++ b/src/Blocks/BlockPressurePlate.h @@ -17,15 +17,16 @@ public: private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 1) + if (a_Position.y <= 0) { return false; } // TODO: check if the block is upside-down slab or upside-down stairs - auto Block = a_Chunk.GetBlock(a_RelPos.addedY(-1)); + + const auto Block = a_Chunk.GetBlock(a_Position.addedY(-1)); switch (Block) { case E_BLOCK_ACACIA_FENCE: @@ -41,7 +42,7 @@ private: } default: { - return (!cBlockInfo::IsTransparent(Block)); + return !cBlockInfo::IsTransparent(Block); } } } diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h index d05c05ba3..bc10985df 100644 --- a/src/Blocks/BlockQuartz.h +++ b/src/Blocks/BlockQuartz.h @@ -18,66 +18,6 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - auto Meta = static_cast(a_Player.GetEquippedItem().m_ItemDamage); - - // Pillar block needs additional direction in the metadata: - if (Meta != E_META_QUARTZ_PILLAR) - { - a_BlockMeta = Meta; - return true; - } - a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); - return true; - } - - - - - - /** Converts the block face of the pillar block's "base" to the block's metadata. */ - inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) - { - switch (a_BlockFace) - { - case BLOCK_FACE_YM: - case BLOCK_FACE_YP: - { - return E_META_QUARTZ_PILLAR; // Top or bottom - } - - case BLOCK_FACE_ZP: - case BLOCK_FACE_ZM: - { - return 0x4; // North or south - } - - case BLOCK_FACE_XP: - case BLOCK_FACE_XM: - { - return 0x3; // East or west - } - - default: - { - return E_META_QUARTZ_PILLAR; - } - } - } - - - - - virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 7c147d48a..d822e728f 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -25,141 +25,8 @@ public: using Super::Super; -private: - - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - a_BlockMeta = FindMeta(a_ChunkInterface, a_PlacedBlockPos); - return a_Player.GetWorld()->DoWithChunkAt(a_PlacedBlockPos, - [this, a_PlacedBlockPos, &a_ChunkInterface](cChunk & a_Chunk) - { - auto RelPos = cChunkDef::AbsoluteToRelative(a_PlacedBlockPos); - return CanBeAt(a_ChunkInterface, RelPos, a_Chunk); - } - ); - } - - - - - - virtual void OnPlaced( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - Vector3i a_BlockPos, - BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta - ) const override - { - Super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_BlockType, a_BlockMeta); - - // Alert diagonal rails: - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); - } - - - - - - virtual void OnBroken( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, - const cEntity * a_Digger - ) const override - { - Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta, a_Digger); - - // Alert diagonal rails: - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); - } - - - - - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override - { - const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); - const auto NewMeta = FindMeta(a_ChunkInterface, a_BlockPos); - if ((Meta != NewMeta) && IsUnstable(a_ChunkInterface, a_BlockPos)) - { - a_ChunkInterface.FastSetBlock(a_BlockPos, m_BlockType, (m_BlockType == E_BLOCK_RAIL) ? NewMeta : NewMeta | (Meta & 0x08)); - } - - Super::OnNeighborChanged(a_ChunkInterface, a_BlockPos, a_WhichNeighbor); - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override - { - if (a_RelPos.y <= 0) - { - return false; - } - if (!cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelPos.addedY(-1)))) - { - return false; - } - - NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelPos); - switch (Meta) - { - case E_META_RAIL_ASCEND_XP: - case E_META_RAIL_ASCEND_XM: - case E_META_RAIL_ASCEND_ZM: - case E_META_RAIL_ASCEND_ZP: - { - // Mapping between the meta and the neighbors that need checking - Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero - static const Vector3i Coords[] = - { - { 1, 0, 0}, // east, XP - {-1, 0, 0}, // west, XM - { 0, 0, -1}, // north, ZM - { 0, 0, 1}, // south, ZP - } ; - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[Meta], BlockType, BlockMeta)) - { - // Too close to the edge, cannot simulate - return true; - } - return cBlockInfo::FullyOccupiesVoxel(BlockType); - } - } - return true; - } - - - - - - NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos) const + static NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, BLOCKTYPE a_RailType) { NIBBLETYPE Meta = 0; char RailsCnt = 0; @@ -234,19 +101,21 @@ private: } if (RailsCnt > 1) { - if (Neighbors[3] && Neighbors[0] && CanThisRailCurve()) + const bool CanCurve = a_RailType == E_BLOCK_RAIL; + + if (Neighbors[3] && Neighbors[0] && CanCurve) { return E_META_RAIL_CURVED_ZP_XP; } - else if (Neighbors[3] && Neighbors[1] && CanThisRailCurve()) + else if (Neighbors[3] && Neighbors[1] && CanCurve) { return E_META_RAIL_CURVED_ZP_XM; } - else if (Neighbors[2] && Neighbors[0] && CanThisRailCurve()) + else if (Neighbors[2] && Neighbors[0] && CanCurve) { return E_META_RAIL_CURVED_ZM_XP; } - else if (Neighbors[2] && Neighbors[1] && CanThisRailCurve()) + else if (Neighbors[2] && Neighbors[1] && CanCurve) { return E_META_RAIL_CURVED_ZM_XM; } @@ -275,7 +144,7 @@ private: return E_META_RAIL_ZM_ZP; } - if (CanThisRailCurve()) + if (CanCurve) { ASSERT(!"Weird neighbor count"); } @@ -283,10 +152,42 @@ private: return Meta; } +private: - bool CanThisRailCurve(void) const + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override { - return m_BlockType == E_BLOCK_RAIL; + if ((a_Position.y <= 0) || !cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_Position.addedY(-1)))) + { + return false; + } + + switch (a_Meta) + { + case E_META_RAIL_ASCEND_XP: + case E_META_RAIL_ASCEND_XM: + case E_META_RAIL_ASCEND_ZM: + case E_META_RAIL_ASCEND_ZP: + { + // Mapping between the meta and the neighbors that need checking + a_Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero + static const Vector3i Coords[] = + { + { 1, 0, 0}, // east, XP + {-1, 0, 0}, // west, XM + { 0, 0, -1}, // north, ZM + { 0, 0, 1}, // south, ZP + } ; + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[a_Meta], BlockType, BlockMeta)) + { + // Too close to the edge, cannot simulate + return true; + } + return cBlockInfo::FullyOccupiesVoxel(BlockType); + } + } + return true; } @@ -521,6 +422,60 @@ private: } + virtual void OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger + ) const override + { + Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta, a_Digger); + + // Alert diagonal rails: + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); + } + + + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override + { + const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); + const auto NewMeta = FindMeta(a_ChunkInterface, a_BlockPos, m_BlockType); + if ((Meta != NewMeta) && IsUnstable(a_ChunkInterface, a_BlockPos)) + { + a_ChunkInterface.FastSetBlock(a_BlockPos, m_BlockType, (m_BlockType == E_BLOCK_RAIL) ? NewMeta : NewMeta | (Meta & 0x08)); + } + + Super::OnNeighborChanged(a_ChunkInterface, a_BlockPos, a_WhichNeighbor); + } + + + virtual void OnPlaced( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, + BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta + ) const override + { + Super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_BlockType, a_BlockMeta); + + // Alert diagonal rails: + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); + } + + virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { // Bit 0x08 is a flag when a_Meta is in the range 0x00--0x05 and 0x0A--0x0F. diff --git a/src/Blocks/BlockRedstone.h b/src/Blocks/BlockRedstone.h index 8a7e35aa1..d77ff151a 100644 --- a/src/Blocks/BlockRedstone.h +++ b/src/Blocks/BlockRedstone.h @@ -19,16 +19,16 @@ public: private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } BLOCKTYPE BelowBlock; NIBBLETYPE BelowBlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BelowBlock, BelowBlockMeta); + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta); if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) { diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h index 97b16f174..4b9650e90 100644 --- a/src/Blocks/BlockRedstoneRepeater.h +++ b/src/Blocks/BlockRedstoneRepeater.h @@ -105,16 +105,16 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } BLOCKTYPE BelowBlock; NIBBLETYPE BelowBlockMeta; - a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BelowBlock, BelowBlockMeta); + a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta); if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) { diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h index ab3f66edc..d32b9b449 100644 --- a/src/Blocks/BlockSapling.h +++ b/src/Blocks/BlockSapling.h @@ -29,9 +29,9 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - return (a_RelPos.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelPos.addedY(-1))); + return (a_Position.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_Position.addedY(-1))); } diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h index 17751a565..f2c4ce4e6 100644 --- a/src/Blocks/BlockSideways.h +++ b/src/Blocks/BlockSideways.h @@ -8,7 +8,6 @@ /** Handler for blocks that have 3 orientations (hay bale, log), specified by the upper 2 bits in meta. -Handles setting the correct orientation on placement. Additionally supports the metadata specifying block sub-type in its lower 2 bits. */ class cBlockSidewaysHandler final : public cBlockHandler @@ -21,66 +20,9 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - NIBBLETYPE Meta = static_cast(a_Player.GetEquippedItem().m_ItemDamage); - a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace, Meta); - return true; - } - - - - - virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { - // Reset the orientation part of meta, keep the sub-type part of meta + // Reset the orientation part of meta, keep the sub-type part of meta: return cItem(m_BlockType, 1, a_BlockMeta & 0x03); } - - - - - - inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_Meta) - { - switch (a_BlockFace) - { - case BLOCK_FACE_YM: - case BLOCK_FACE_YP: - { - return a_Meta; // Top or bottom, just return original - } - - case BLOCK_FACE_ZP: - case BLOCK_FACE_ZM: - { - return a_Meta | 0x8; // North or south - } - - case BLOCK_FACE_XP: - case BLOCK_FACE_XM: - { - return a_Meta | 0x4; // East or west - } - - case BLOCK_FACE_NONE: - { - break; - } - } - UNREACHABLE("Unsupported block face"); - } } ; - - - - diff --git a/src/Blocks/BlockSignPost.h b/src/Blocks/BlockSignPost.h index 8d31ae7fa..b96498cbd 100644 --- a/src/Blocks/BlockSignPost.h +++ b/src/Blocks/BlockSignPost.h @@ -17,20 +17,6 @@ public: using Super::Super; - /** Converts the (player) rotation to placed-signpost block meta. */ - static NIBBLETYPE RotationToMetaData(double a_Rotation) - { - a_Rotation += 180 + (180 / 16); // So it's not aligned with axis - if (a_Rotation > 360) - { - a_Rotation -= 360; - } - - a_Rotation = (a_Rotation / 360) * 16; - - return (static_cast(a_Rotation)) % 16; - } - private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override @@ -42,14 +28,15 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } - BLOCKTYPE Type = a_Chunk.GetBlock(a_RelPos.addedY(-1)); - return ((Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type)); + + BLOCKTYPE Type = a_Chunk.GetBlock(a_Position.addedY(-1)); + return (Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type); } diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h index 98f327b5b..566c88c71 100644 --- a/src/Blocks/BlockSlab.h +++ b/src/Blocks/BlockSlab.h @@ -46,64 +46,25 @@ private: } - - - - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { - a_BlockType = m_BlockType; - NIBBLETYPE Meta = static_cast(a_Player.GetEquippedItem().m_ItemDamage); - - // Set the correct metadata based on player equipped item (i.e. a_BlockMeta not initialised yet) - switch (a_ClickedBlockFace) + /* Double slab combining uses build collision checks to replace single slabs with double slabs in the right conditions. + For us to be replaced, the player must be: + 1. Placing the same slab material. + 2. Placing the same slab sub-kind (and existing slab is single). */ + if ((m_BlockType != a_HeldItem.m_ItemType) || ((a_Meta & 0x07) != a_HeldItem.m_ItemDamage)) { - case BLOCK_FACE_TOP: - { - // Bottom half slab block - a_BlockMeta = Meta & 0x07; - break; - } - case BLOCK_FACE_BOTTOM: - { - // Top half slab block - a_BlockMeta = Meta | 0x08; - break; - } - case BLOCK_FACE_EAST: - case BLOCK_FACE_NORTH: - case BLOCK_FACE_SOUTH: - case BLOCK_FACE_WEST: - { - if (a_CursorPos.y > 7) - { - // Cursor at top half of block, place top slab - a_BlockMeta = Meta | 0x08; break; - } - else - { - // Cursor at bottom half of block, place bottom slab - a_BlockMeta = Meta & 0x07; break; - } - } - case BLOCK_FACE_NONE: return false; - } // switch (a_BlockFace) - - // Check if the block at the coordinates is a single slab. Eligibility for combining has already been processed in ClientHandle - // Changed to-be-placed to a double slab if we are clicking on a single slab, as opposed to placing one for the first time - if (IsAnySlabType(a_ChunkInterface.GetBlock(a_PlacedBlockPos))) - { - a_BlockType = GetDoubleSlabType(m_BlockType); - a_BlockMeta = a_BlockMeta & 0x07; + return false; } - return true; + const bool IsTopSlab = (a_Meta & 0x08) == 0x08; + const auto CanClickCombine = ((a_ClickedBlockFace == BLOCK_FACE_TOP) && !IsTopSlab) || ((a_ClickedBlockFace == BLOCK_FACE_BOTTOM) && IsTopSlab); + + /* When the player clicks on us directly, we'll combine if we're + a bottom slab and he clicked the top, or vice versa. Clicking on the sides will not combine. + However, when indirectly clicked (on the side of another block, that caused placement to go to us) + the conditions are exactly the opposite. */ + return a_ClickedDirectly ? CanClickCombine : !CanClickCombine; } @@ -131,24 +92,6 @@ private: - /** Converts the single-slab blocktype to its equivalent double-slab blocktype */ - static BLOCKTYPE GetDoubleSlabType(BLOCKTYPE a_SingleSlabBlockType) - { - switch (a_SingleSlabBlockType) - { - case E_BLOCK_STONE_SLAB: return E_BLOCK_DOUBLE_STONE_SLAB; - case E_BLOCK_WOODEN_SLAB: return E_BLOCK_DOUBLE_WOODEN_SLAB; - case E_BLOCK_RED_SANDSTONE_SLAB: return E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB; - case E_BLOCK_PURPUR_SLAB: return E_BLOCK_PURPUR_DOUBLE_SLAB; - } - ASSERT(!"Unhandled slab type!"); - return E_BLOCK_AIR; - } - - - - - virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override { // Toggle the 4th bit - up / down: diff --git a/src/Blocks/BlockSnow.h b/src/Blocks/BlockSnow.h index 299ec9f62..f3fa87a1b 100644 --- a/src/Blocks/BlockSnow.h +++ b/src/Blocks/BlockSnow.h @@ -20,58 +20,21 @@ private: enum { - FullBlockMeta = 7 // Meta value of a full-height snow block + FullBlockMeta = 7 // Meta value of a full-height snow block. }; - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - a_BlockType = m_BlockType; - - // Check if incrementing existing snow height: - BLOCKTYPE BlockBeforePlacement; - NIBBLETYPE MetaBeforePlacement; - a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos, BlockBeforePlacement, MetaBeforePlacement); - if ((BlockBeforePlacement == E_BLOCK_SNOW) && (MetaBeforePlacement < FullBlockMeta)) - { - // Only increment if: - // - A snow block was already there (not first time placement) AND - // - Height is smaller than the maximum possible - a_BlockMeta = MetaBeforePlacement + 1; - return true; - } - - // First time placement, check placement is valid - a_BlockMeta = 0; - BLOCKTYPE BlockBelow; - NIBBLETYPE MetaBelow; - return ( - (a_PlacedBlockPos.y > 0) && - a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos.addedY(-1), BlockBelow, MetaBelow) && - CanBeOn(BlockBelow, MetaBelow) - ); - } - - - - - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { - if ((a_Player.GetEquippedItem().m_ItemType == E_BLOCK_SNOW) && (a_Meta < FullBlockMeta)) + if (a_Meta == 0) { - return true; // If a player is holding a (thin) snow block and it's size can be increased, return collision ignored + return true; // If at normal snowfall height (lowest), we ignore collision. } - if (a_Meta == 0) + // Special case if a player is holding a (thin) snow block and its size can be increased: + if ((a_HeldItem.m_ItemType == E_BLOCK_SNOW) && (a_Meta < FullBlockMeta)) { - return true; // If at normal snowfall height (lowest), we ignore collision + return !a_ClickedDirectly || (a_ClickedBlockFace == BLOCK_FACE_YP); // If clicked an adjacent block, or clicked YP directly, we ignore collision. } return false; @@ -83,7 +46,7 @@ private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { - // No drop unless dug up with a shovel + // No drop unless dug up with a shovel: if ((a_Tool == nullptr) || !ItemCategory::IsShovel(a_Tool->m_ItemType)) { return {}; @@ -104,13 +67,13 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } - auto BelowPos = a_RelPos.addedY(-1); + auto BelowPos = a_Position.addedY(-1); auto BlockBelow = a_Chunk.GetBlock(BelowPos); auto MetaBelow = a_Chunk.GetMeta(BelowPos); return CanBeOn(BlockBelow, MetaBelow); @@ -141,7 +104,7 @@ private: /** Returns true if snow can be placed on top of a block with the given type and meta. */ static bool CanBeOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { - // If block below is snowable, or it is a thin slow block and is a full thin snow block, say yay + // If block below is snowable, or it is a thin snow block and is a full thin snow block, say yay: return ( cBlockInfo::IsSnowable(a_BlockType) || ( diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h index 701ad38e1..55a9e877e 100644 --- a/src/Blocks/BlockStairs.h +++ b/src/Blocks/BlockStairs.h @@ -8,9 +8,9 @@ class cBlockStairsHandler final : - public cClearMetaOnDrop> + public cClearMetaOnDrop> { - using Super = cClearMetaOnDrop>; + using Super = cClearMetaOnDrop>; public: @@ -18,74 +18,6 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - UNUSED(a_ChunkInterface); - UNUSED(a_PlacedBlockPos); - UNUSED(a_CursorPos); - a_BlockType = m_BlockType; - a_BlockMeta = RotationToMetaData(a_Player.GetYaw()); - switch (a_ClickedBlockFace) - { - case BLOCK_FACE_TOP: break; - case BLOCK_FACE_BOTTOM: a_BlockMeta = a_BlockMeta | 0x4; break; // When placing onto a bottom face, always place an upside-down stairs block - case BLOCK_FACE_EAST: - case BLOCK_FACE_NORTH: - case BLOCK_FACE_SOUTH: - case BLOCK_FACE_WEST: - { - // When placing onto a sideways face, check cursor, if in top half, make it an upside-down stairs block - if (a_CursorPos.y > 8) - { - a_BlockMeta |= 0x4; - } - break; - } - case BLOCK_FACE_NONE: return false; - } - return true; - } - - - - - - static NIBBLETYPE RotationToMetaData(double a_Rotation) - { - a_Rotation += 90 + 45; // So its not aligned with axis - if (a_Rotation > 360) - { - a_Rotation -= 360; - } - if ((a_Rotation >= 0) && (a_Rotation < 90)) - { - return 0x0; - } - else if ((a_Rotation >= 180) && (a_Rotation < 270)) - { - return 0x1; - } - else if ((a_Rotation >= 90) && (a_Rotation < 180)) - { - return 0x2; - } - else - { - return 0x3; - } - } - - - - - virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override { // Toggle bit 3: diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h index 1b6670264..f6686b25a 100644 --- a/src/Blocks/BlockStems.h +++ b/src/Blocks/BlockStems.h @@ -56,9 +56,9 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - return ((a_RelPos.y > 0) && (a_Chunk.GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_FARMLAND)); + return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND); } diff --git a/src/Blocks/BlockSugarcane.h b/src/Blocks/BlockSugarcane.h index 1e802560d..bf5ae5e73 100644 --- a/src/Blocks/BlockSugarcane.h +++ b/src/Blocks/BlockSugarcane.h @@ -27,14 +27,14 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } - switch (a_Chunk.GetBlock(a_RelPos.addedY(-1))) + switch (a_Chunk.GetBlock(a_Position.addedY(-1))) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: @@ -52,7 +52,7 @@ private: { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[i], BlockType, BlockMeta)) + if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta)) { // Too close to the edge, cannot simulate return true; diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h index 83f955a80..ea638c878 100644 --- a/src/Blocks/BlockTallGrass.h +++ b/src/Blocks/BlockTallGrass.h @@ -20,7 +20,7 @@ public: private: - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } @@ -52,14 +52,14 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - if (a_RelPos.y <= 0) + if (a_Position.y <= 0) { return false; } - BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_RelPos.addedY(-1)); + BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_Position.addedY(-1)); return IsBlockTypeOfDirt(BelowBlock); } diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h index c7bd4dcc8..0b96ad246 100644 --- a/src/Blocks/BlockTorch.h +++ b/src/Blocks/BlockTorch.h @@ -18,91 +18,6 @@ public: using Super::Super; -protected: - - ~cBlockTorchBaseHandler() = default; - -private: - - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - BLOCKTYPE ClickedBlockType; - NIBBLETYPE ClickedBlockMeta; - auto ClickedBlockPos = AddFaceDirection(a_PlacedBlockPos, a_ClickedBlockFace, true); - a_ChunkInterface.GetBlockTypeMeta(ClickedBlockPos, ClickedBlockType, ClickedBlockMeta); - if (!CanBePlacedOn(ClickedBlockType, ClickedBlockMeta, a_ClickedBlockFace)) - { - // Couldn't be placed on whatever face was clicked, last ditch resort - find another face - a_ClickedBlockFace = FindSuitableFace(a_ChunkInterface, a_PlacedBlockPos); // Set a_BlockFace to a valid direction which will be converted later to a metadata - if (a_ClickedBlockFace == BLOCK_FACE_NONE) - { - // No attachable face found - don't place the torch - return false; - } - } - a_BlockType = m_BlockType; - a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); - return true; - } - - - - - - /** Converts the block face of the neighbor to which the torch is attached, to the torch block's meta. */ - inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) - { - switch (a_NeighborBlockFace) - { - case BLOCK_FACE_BOTTOM: ASSERT(!"Shouldn't be getting this face"); return 0; - case BLOCK_FACE_TOP: return E_META_TORCH_FLOOR; - case BLOCK_FACE_EAST: return E_META_TORCH_EAST; - case BLOCK_FACE_WEST: return E_META_TORCH_WEST; - case BLOCK_FACE_NORTH: return E_META_TORCH_NORTH; - case BLOCK_FACE_SOUTH: return E_META_TORCH_SOUTH; - case BLOCK_FACE_NONE: - { - ASSERT(!"Unhandled torch direction!"); - break; - } - } - return 0x0; - } - - - - - - /** Converts the torch block's meta to the block face of the neighbor to which the torch is attached. */ - inline static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) - { - switch (a_MetaData) - { - case 0: return BLOCK_FACE_TOP; // By default, the torches stand on the ground - case E_META_TORCH_FLOOR: return BLOCK_FACE_TOP; - case E_META_TORCH_EAST: return BLOCK_FACE_EAST; - case E_META_TORCH_WEST: return BLOCK_FACE_WEST; - case E_META_TORCH_NORTH: return BLOCK_FACE_NORTH; - case E_META_TORCH_SOUTH: return BLOCK_FACE_SOUTH; - default: - { - ASSERT(!"Unhandled torch metadata"); - break; - } - } - return BLOCK_FACE_TOP; - } - - - - /** Returns true if the torch can be placed on the specified block's face. */ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace) @@ -163,37 +78,40 @@ private: } } +protected: + ~cBlockTorchBaseHandler() = default; +private: - - /** Returns a suitable neighbor's blockface to place the torch at the specified pos - Returns BLOCK_FACE_NONE on failure */ - static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, const Vector3i a_TorchPos) + /** Converts the torch block's meta to the block face of the neighbor to which the torch is attached. */ + inline static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) { - for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all faces + switch (a_MetaData) { - auto Face = static_cast(i); - auto NeighborPos = AddFaceDirection(a_TorchPos, Face, true); - BLOCKTYPE NeighborBlockType; - NIBBLETYPE NeighborBlockMeta; - a_ChunkInterface.GetBlockTypeMeta(NeighborPos, NeighborBlockType, NeighborBlockMeta); - if (CanBePlacedOn(NeighborBlockType, NeighborBlockMeta, Face)) + case 0: return BLOCK_FACE_TOP; // By default, the torches stand on the ground + case E_META_TORCH_FLOOR: return BLOCK_FACE_TOP; + case E_META_TORCH_EAST: return BLOCK_FACE_EAST; + case E_META_TORCH_WEST: return BLOCK_FACE_WEST; + case E_META_TORCH_NORTH: return BLOCK_FACE_NORTH; + case E_META_TORCH_SOUTH: return BLOCK_FACE_SOUTH; + default: { - return Face; + ASSERT(!"Unhandled torch metadata"); + break; } } - return BLOCK_FACE_NONE; + return BLOCK_FACE_TOP; } - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - auto Face = MetaDataToBlockFace(a_Chunk.GetMeta(a_RelPos)); - auto NeighborRelPos = AddFaceDirection(a_RelPos, Face, true); + auto Face = MetaDataToBlockFace(a_Meta); + auto NeighborRelPos = AddFaceDirection(a_Position, Face, true); BLOCKTYPE NeighborBlockType; NIBBLETYPE NeighborBlockMeta; if (!a_Chunk.UnboundedRelGetBlock(NeighborRelPos, NeighborBlockType, NeighborBlockMeta)) diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h index cef7fb6e9..7f6f70e1e 100644 --- a/src/Blocks/BlockTrapdoor.h +++ b/src/Blocks/BlockTrapdoor.h @@ -71,74 +71,6 @@ private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - if (a_ClickedBlockFace == BLOCK_FACE_YP) - { - // Trapdoor is placed on top of a block. - // Engage yaw rotation to determine hinge direction: - return Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta); - } - else if (a_ClickedBlockFace == BLOCK_FACE_YM) - { - // Trapdoor is placed on bottom of a block. - // Engage yaw rotation to determine hinge direction: - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, a_BlockMeta)) - { - return false; - } - - // Toggle 'Move up half-block' bit on: - a_BlockMeta |= 0x8; - - return true; - } - - // Placement on block sides; hinge direction is determined by which side was clicked: - a_BlockType = m_BlockType; - a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace); - - if (a_CursorPos.y > 7) - { - // Trapdoor is placed on a higher half of a vertical block. - // Toggle 'Move up half-block' bit on: - a_BlockMeta |= 0x8; - } - - return true; - } - - - - - - inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) - { - switch (a_BlockFace) - { - case BLOCK_FACE_ZP: return 0x1; - case BLOCK_FACE_ZM: return 0x0; - case BLOCK_FACE_XP: return 0x3; - case BLOCK_FACE_XM: return 0x2; - default: - { - ASSERT(!"Unhandled block face!"); - return 0; - } - } - } - - - - - inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x3) diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h index 0d58bb084..ae553d66f 100644 --- a/src/Blocks/BlockTripwireHook.h +++ b/src/Blocks/BlockTripwireHook.h @@ -30,57 +30,9 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - a_BlockType = m_BlockType; - - switch (a_ClickedBlockFace) - { - case BLOCK_FACE_XM: - { - a_BlockMeta = 0x1; - return true; - } - case BLOCK_FACE_XP: - { - a_BlockMeta = 0x3; - return true; - } - case BLOCK_FACE_ZM: - { - a_BlockMeta = 0x2; - return true; - } - case BLOCK_FACE_ZP: - { - a_BlockMeta = 0x0; - return true; - } - case BLOCK_FACE_NONE: - case BLOCK_FACE_YM: - case BLOCK_FACE_YP: - { - return false; - } - } - UNREACHABLE("Unsupported block face"); - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override - { - const auto Meta = a_Chunk.GetMeta(a_RelPos); - const auto RearPosition = AddFaceDirection(a_RelPos, MetadataToDirection(Meta), true); + const auto RearPosition = AddFaceDirection(a_Position, MetadataToDirection(a_Meta), true); BLOCKTYPE NeighborBlockType; if (!a_Chunk.UnboundedRelGetBlockType(RearPosition, NeighborBlockType)) diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h index 51f6112bc..da4d6dfc3 100644 --- a/src/Blocks/BlockVine.h +++ b/src/Blocks/BlockVine.h @@ -17,33 +17,14 @@ public: private: - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - // TODO: Disallow placement where the vine doesn't attach to something properly - BLOCKTYPE BlockType = 0; - NIBBLETYPE BlockMeta; - a_ChunkInterface.GetBlockTypeMeta(a_PlacedBlockPos, BlockType, BlockMeta); - if (BlockType == m_BlockType) - { - a_BlockMeta = BlockMeta | DirectionToMetaData(a_ClickedBlockFace); - } - else - { - a_BlockMeta = DirectionToMetaData(a_ClickedBlockFace); - } - a_BlockType = m_BlockType; - return true; - } - + static const NIBBLETYPE VINE_LOST_SUPPORT = 16; + static const NIBBLETYPE VINE_UNCHANGED = 17; + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override + { + return GetMaxMeta(a_Chunk, a_Position, a_Meta) != VINE_LOST_SUPPORT; + } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override @@ -60,22 +41,6 @@ private: - static NIBBLETYPE DirectionToMetaData(char a_BlockFace) - { - switch (a_BlockFace) - { - case BLOCK_FACE_NORTH: return 0x1; - case BLOCK_FACE_SOUTH: return 0x4; - case BLOCK_FACE_WEST: return 0x8; - case BLOCK_FACE_EAST: return 0x2; - default: return 0x0; - } - } - - - - - static char MetaDataToDirection(NIBBLETYPE a_MetaData) { switch (a_MetaData) @@ -122,8 +87,9 @@ private: - /** Returns the meta that has the maximum allowable sides of the vine, given the surroundings */ - static NIBBLETYPE GetMaxMeta(cChunk & a_Chunk, Vector3i a_RelPos) + /** Returns the meta that has the maximum allowable sides of the vine, given the surroundings and current vine meta. + Returns special values for a vine that can continue to exist unchanged, or must die completely. */ + static NIBBLETYPE GetMaxMeta(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta) { static const struct { @@ -136,21 +102,41 @@ private: { 0, -1, 4}, // north, ZM { 1, 0, 8}, // east, XP } ; - NIBBLETYPE res = 0; + + NIBBLETYPE MaxMeta = 0; for (auto & Coord : Coords) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; - auto checkPos = a_RelPos.addedXZ(Coord.x, Coord.z); + auto checkPos = a_Position.addedXZ(Coord.x, Coord.z); if ( a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) && IsBlockAttachable(BlockType) ) { - res |= Coord.Bit; + MaxMeta |= Coord.Bit; } } - return res; + + // 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)) + { + MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1)); + } + + 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))); + if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine. + { + return VINE_LOST_SUPPORT; + } + + return Common; + } + + return VINE_UNCHANGED; } @@ -162,28 +148,25 @@ private: a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { - const auto a_RelPos = cChunkDef::AbsoluteToRelative(a_BlockPos); - NIBBLETYPE CurMeta = a_Chunk.GetMeta(a_RelPos); - NIBBLETYPE MaxMeta = GetMaxMeta(a_Chunk, a_RelPos); + const auto Position = cChunkDef::AbsoluteToRelative(a_BlockPos); + const auto MaxMeta = GetMaxMeta(a_Chunk, Position, a_Chunk.GetMeta(Position)); - // Check if vine above us, add its meta to MaxMeta - if ((a_RelPos.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == m_BlockType)) + if (MaxMeta == VINE_UNCHANGED) { - MaxMeta |= a_Chunk.GetMeta(a_RelPos.addedY(1)); + return false; } - NIBBLETYPE Common = CurMeta & MaxMeta; // Neighbors that we have and are legal - if (Common != CurMeta) + // There is a neighbor missing, need to update the meta or even destroy the block. + + if (MaxMeta == VINE_LOST_SUPPORT) { - // There is a neighbor missing, need to update the meta or even destroy the block - bool HasTop = (a_RelPos.y < cChunkDef::Height - 1) && IsBlockAttachable(a_Chunk.GetBlock(a_RelPos.addedY(1))); - if ((Common == 0) && !HasTop) - { - // The vine just lost all its support, destroy the block: - a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0); - return false; - } - a_Chunk.SetBlock(a_RelPos, m_BlockType, Common); + // The vine just lost all its support, destroy the block: + a_Chunk.SetBlock(Position, E_BLOCK_AIR, 0); + } + else + { + // It lost some of its support, set it to what remains (SetBlock to notify neighbors): + a_Chunk.SetBlock(Position, E_BLOCK_VINES, MaxMeta); } return false; @@ -194,9 +177,9 @@ private: - virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override + virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { - return true; + return !a_ClickedDirectly || (a_HeldItem.m_ItemType != m_BlockType); } diff --git a/src/Blocks/BlockWallSign.h b/src/Blocks/BlockWallSign.h index 2e6f7a45b..f19e408fa 100644 --- a/src/Blocks/BlockWallSign.h +++ b/src/Blocks/BlockWallSign.h @@ -17,25 +17,6 @@ public: using Super::Super; - /** Converts the block face of the neighbor to which the wallsign is attached to the wallsign block's meta. */ - static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) - { - switch (a_NeighborBlockFace) - { - case BLOCK_FACE_ZM: return 0x02; - case BLOCK_FACE_ZP: return 0x03; - case BLOCK_FACE_XM: return 0x04; - case BLOCK_FACE_XP: return 0x05; - case BLOCK_FACE_NONE: - case BLOCK_FACE_YP: - case BLOCK_FACE_YM: - { - break; - } - } - return 0x02; - } - private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override @@ -47,16 +28,16 @@ private: - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { - auto NeighborPos = a_RelPos + GetOffsetBehindTheSign(a_Chunk.GetMeta(a_RelPos)); + auto NeighborPos = a_Position + GetOffsetBehindTheSign(a_Meta); BLOCKTYPE NeighborType; if (!a_Chunk.UnboundedRelGetBlockType(NeighborPos, NeighborType)) { // The neighbor is not accessible (unloaded chunk), bail out without changing this return true; } - return ((NeighborType == E_BLOCK_WALLSIGN) || (NeighborType == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(NeighborType)); + return (NeighborType == E_BLOCK_WALLSIGN) || (NeighborType == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(NeighborType); } diff --git a/src/Blocks/Mixins.h b/src/Blocks/Mixins.h index 42b437ba7..23a4be225 100644 --- a/src/Blocks/Mixins.h +++ b/src/Blocks/Mixins.h @@ -167,27 +167,6 @@ public: using Super::Super; - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, cPlayer & a_Player, - const Vector3i a_BlockPos, - eBlockFace a_BlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override - { - NIBBLETYPE BaseMeta; - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_BlockPos, a_BlockFace, a_CursorPos, a_BlockType, BaseMeta)) - { - return false; - } - - a_BlockMeta = (BaseMeta & ~BitMask) | YawToMetaData(a_Player.GetYaw()); - return true; - } - - - - /** Converts the rotation value as returned by cPlayer::GetYaw() to the appropriate metadata value for a block placed by a player facing that way */ @@ -241,31 +220,26 @@ public: using Super::Super; -protected: - - ~cPitchYawRotator() = default; - virtual bool GetPlacementBlockTypeMeta( - cChunkInterface & a_ChunkInterface, - cPlayer & a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) const override + /** Converts the rotation and pitch values as returned by cPlayer::GetYaw() and cPlayer::GetPitch() + respectively to the appropriate metadata value for a block placed by a player facing that way */ + static NIBBLETYPE PitchYawToMetaData(double a_Rotation, double a_Pitch) { - NIBBLETYPE BaseMeta; - if (!Super::GetPlacementBlockTypeMeta(a_ChunkInterface, a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, a_BlockType, BaseMeta)) + if (a_Pitch >= 50) { - return false; + return Up; + } + else if (a_Pitch <= -50) + { + return Down; } - a_BlockMeta = (BaseMeta & ~BitMask) | PitchYawToMetaData(a_Player.GetYaw(), a_Player.GetPitch()); - return true; + return Super::YawToMetaData(a_Rotation); } +protected: - + ~cPitchYawRotator() = default; virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override @@ -279,24 +253,4 @@ protected: // Not Facing Up or Down; No change. return a_Meta; } - - - - - - /** Converts the rotation and pitch values as returned by cPlayer::GetYaw() and cPlayer::GetPitch() - respectively to the appropriate metadata value for a block placed by a player facing that way */ - static NIBBLETYPE PitchYawToMetaData(double a_Rotation, double a_Pitch) - { - if (a_Pitch >= 50) - { - return Up; - } - else if (a_Pitch <= -50) - { - return Down; - } - - return Super::YawToMetaData(a_Rotation); - } }; diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index b610bd9ac..b3fc9878d 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -54,10 +54,10 @@ public: virtual std::vector SpawnSplitExperienceOrbs(Vector3d a_Pos, int a_Reward) = 0; /** Sends the block on those coords to the player */ - virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer & a_Player) = 0; + virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, const cPlayer & a_Player) = 0; /** Sends the block on those coords to the player */ - inline void SendBlockTo(const Vector3i a_BlockPos, cPlayer & a_Player) + inline void SendBlockTo(const Vector3i a_BlockPos, const cPlayer & a_Player) { SendBlockTo(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Player); } -- cgit v1.2.3