summaryrefslogtreecommitdiffstats
path: root/src/Items/ItemDoor.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Items/ItemDoor.h96
1 files changed, 73 insertions, 23 deletions
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;
}
} ;