From ccdf03daaf880dd0c89a03b50c11eb083ee1cfb0 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 24 Dec 2014 07:20:17 +0100 Subject: Refactored all player block placing to go through hooks. Fixes #1618. --- src/Items/ItemDoor.h | 96 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 23 deletions(-) (limited to 'src/Items/ItemDoor.h') diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h index cd5baf44f..dbba26728 100644 --- a/src/Items/ItemDoor.h +++ b/src/Items/ItemDoor.h @@ -3,6 +3,7 @@ #include "ItemHandler.h" #include "../World.h" +#include "../Blocks/BlockDoor.h" @@ -18,27 +19,43 @@ public: } - virtual bool IsPlaceable(void) override - { - return true; - } - virtual bool GetPlacementBlockTypeMeta( - cWorld * a_World, cPlayer * a_Player, + virtual bool OnPlayerPlace( + cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta + int a_CursorX, int a_CursorY, int a_CursorZ ) override { + // Vanilla only allows door placement while clicking on the top face of the block below the door: + if (a_BlockFace != BLOCK_FACE_NONE) + { + return false; + } + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + + // Door (bottom block) can be placed in Y range of [1, 254]: + if ((a_BlockY < 1) || (a_BlockY + 2 >= cChunkDef::Height)) + { + return false; + } + + // The door needs a compatible block below it: + if ((a_BlockY > 0) && cBlockDoorHandler::CanBeOn(a_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) + { + return false; + } + + // Get the block type of the door to place: + BLOCKTYPE BlockType; switch (m_ItemType) { - case E_ITEM_WOODEN_DOOR: a_BlockType = E_BLOCK_WOODEN_DOOR; break; - case E_ITEM_IRON_DOOR: a_BlockType = E_BLOCK_IRON_DOOR; break; - case E_ITEM_SPRUCE_DOOR: a_BlockType = E_BLOCK_SPRUCE_DOOR; break; - case E_ITEM_BIRCH_DOOR: a_BlockType = E_BLOCK_BIRCH_DOOR; break; - case E_ITEM_JUNGLE_DOOR: a_BlockType = E_BLOCK_JUNGLE_DOOR; break; - case E_ITEM_DARK_OAK_DOOR: a_BlockType = E_BLOCK_DARK_OAK_DOOR; break; - case E_ITEM_ACACIA_DOOR: a_BlockType = E_BLOCK_ACACIA_DOOR; break; + case E_ITEM_WOODEN_DOOR: BlockType = E_BLOCK_WOODEN_DOOR; break; + case E_ITEM_IRON_DOOR: BlockType = E_BLOCK_IRON_DOOR; break; + case E_ITEM_SPRUCE_DOOR: BlockType = E_BLOCK_SPRUCE_DOOR; break; + case E_ITEM_BIRCH_DOOR: BlockType = E_BLOCK_BIRCH_DOOR; break; + case E_ITEM_JUNGLE_DOOR: BlockType = E_BLOCK_JUNGLE_DOOR; break; + case E_ITEM_DARK_OAK_DOOR: BlockType = E_BLOCK_DARK_OAK_DOOR; break; + case E_ITEM_ACACIA_DOOR: BlockType = E_BLOCK_ACACIA_DOOR; break; default: { ASSERT(!"Unhandled door type"); @@ -46,14 +63,47 @@ public: } } - cChunkInterface ChunkInterface(a_World->GetChunkMap()); - bool Meta = BlockHandler(a_BlockType)->GetPlacementBlockTypeMeta( - ChunkInterface, a_Player, - a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, - a_CursorX, a_CursorY, a_CursorZ, - a_BlockType, a_BlockMeta - ); - return Meta; + // Check the two blocks that will get replaced by the door: + BLOCKTYPE LowerBlockType = a_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ); + BLOCKTYPE UpperBlockType = a_World.GetBlock(a_BlockX, a_BlockY + 2, a_BlockZ); + if ( + !cBlockDoorHandler::CanReplaceBlock(LowerBlockType) || + !cBlockDoorHandler::CanReplaceBlock(UpperBlockType)) + { + return false; + } + + // Get the coords of the neighboring blocks: + NIBBLETYPE LowerBlockMeta = cBlockDoorHandler::PlayerYawToMetaData(a_Player.GetYaw()); + Vector3i RelDirToOutside = cBlockDoorHandler::GetRelativeDirectionToOutside(LowerBlockMeta); + Vector3i LeftNeighborPos = RelDirToOutside; + LeftNeighborPos.TurnCCW(); + LeftNeighborPos.Move(a_BlockX, a_BlockY, a_BlockZ); + Vector3i RightNeighborPos = RelDirToOutside; + RightNeighborPos.TurnCW(); + RightNeighborPos.Move(a_BlockX, a_BlockY, a_BlockZ); + + // Decide whether the hinge is on the left (default) or on the right: + NIBBLETYPE UpperBlockMeta = 0x08; + if ( + cBlockDoorHandler::IsDoorBlockType(a_World.GetBlock(LeftNeighborPos)) || // The block to the left is a door block + cBlockInfo::IsSolid(a_World.GetBlock(RightNeighborPos)) // The block to the right is solid + ) + { + UpperBlockMeta = 0x09; // Upper block | hinge on right + } + + // Set the blocks: + sSetBlockVector blks; + blks.emplace_back(a_BlockX, a_BlockY, a_BlockZ, BlockType, LowerBlockMeta); + blks.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, BlockType, UpperBlockMeta); + return a_Player.PlaceBlocks(blks); + } + + + virtual bool IsPlaceable(void) override + { + return true; } } ; -- cgit v1.2.3