2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "ItemHandler.h"
|
|
|
|
#include "../World.h"
|
2014-12-24 01:20:17 -05:00
|
|
|
#include "../Blocks/BlockDoor.h"
|
2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cItemDoorHandler :
|
|
|
|
public cItemHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cItemDoorHandler(int a_ItemType) :
|
|
|
|
cItemHandler(a_ItemType)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
virtual bool OnPlayerPlace(
|
|
|
|
cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
|
2014-07-17 16:50:58 -04:00
|
|
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
2014-12-24 01:20:17 -05:00
|
|
|
int a_CursorX, int a_CursorY, int a_CursorZ
|
2013-07-29 07:13:03 -04:00
|
|
|
) override
|
|
|
|
{
|
2014-12-24 01:20:17 -05:00
|
|
|
// Vanilla only allows door placement while clicking on the top face of the block below the door:
|
2014-12-24 19:00:51 -05:00
|
|
|
if (a_BlockFace != BLOCK_FACE_TOP)
|
2014-12-24 01:20:17 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
|
|
|
|
|
|
|
// Door (bottom block) can be placed in Y range of [1, 254]:
|
2015-02-14 17:11:38 -05:00
|
|
|
if ((a_BlockY < 1) || (a_BlockY >= cChunkDef::Height - 2))
|
2014-12-24 01:20:17 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The door needs a compatible block below it:
|
2015-04-07 11:51:38 -04:00
|
|
|
if (!cBlockDoorHandler::CanBeOn(a_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ), a_World.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ)))
|
2014-12-24 01:20:17 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the block type of the door to place:
|
|
|
|
BLOCKTYPE BlockType;
|
2014-09-26 13:45:03 -04:00
|
|
|
switch (m_ItemType)
|
|
|
|
{
|
2014-12-24 01:20:17 -05:00
|
|
|
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;
|
2014-09-11 10:33:52 -04:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
ASSERT(!"Unhandled door type");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2015-02-05 02:10:46 -05:00
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
// Check the two blocks that will get replaced by the door:
|
2015-02-05 02:10:46 -05:00
|
|
|
BLOCKTYPE LowerBlockType = a_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
|
|
|
BLOCKTYPE UpperBlockType = a_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
|
2014-12-24 01:20:17 -05:00
|
|
|
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;
|
2015-02-28 11:16:21 -05:00
|
|
|
LeftNeighborPos.TurnCW();
|
2014-12-24 01:20:17 -05:00
|
|
|
LeftNeighborPos.Move(a_BlockX, a_BlockY, a_BlockZ);
|
|
|
|
Vector3i RightNeighborPos = RelDirToOutside;
|
2015-02-28 11:16:21 -05:00
|
|
|
RightNeighborPos.TurnCCW();
|
2014-12-24 01:20:17 -05:00
|
|
|
RightNeighborPos.Move(a_BlockX, a_BlockY, a_BlockZ);
|
|
|
|
|
|
|
|
// Decide whether the hinge is on the left (default) or on the right:
|
|
|
|
NIBBLETYPE UpperBlockMeta = 0x08;
|
2015-02-28 11:16:21 -05:00
|
|
|
BLOCKTYPE LeftNeighborBlock = a_World.GetBlock(LeftNeighborPos);
|
|
|
|
BLOCKTYPE RightNeighborBlock = a_World.GetBlock(RightNeighborPos);
|
|
|
|
/*
|
|
|
|
// DEBUG:
|
|
|
|
LOGD("Door being placed at {%d, %d, %d}", a_BlockX, a_BlockY, a_BlockZ);
|
|
|
|
LOGD("RelDirToOutside: {%d, %d, %d}", RelDirToOutside.x, RelDirToOutside.y, RelDirToOutside.z);
|
|
|
|
LOGD("Left neighbor at {%d, %d, %d}: %d (%s)", LeftNeighborPos.x, LeftNeighborPos.y, LeftNeighborPos.z, LeftNeighborBlock, ItemTypeToString(LeftNeighborBlock).c_str());
|
|
|
|
LOGD("Right neighbor at {%d, %d, %d}: %d (%s)", RightNeighborPos.x, RightNeighborPos.y, RightNeighborPos.z, RightNeighborBlock, ItemTypeToString(RightNeighborBlock).c_str());
|
|
|
|
*/
|
2014-12-24 01:20:17 -05:00
|
|
|
if (
|
2015-02-28 11:16:21 -05:00
|
|
|
cBlockDoorHandler::IsDoorBlockType(LeftNeighborBlock) || // The block to the left is a door block
|
|
|
|
(
|
|
|
|
cBlockInfo::IsSolid(RightNeighborBlock) && // The block to the right is solid...
|
|
|
|
!cBlockDoorHandler::IsDoorBlockType(RightNeighborBlock) // ... but not a door
|
|
|
|
)
|
2014-12-24 01:20:17 -05:00
|
|
|
)
|
|
|
|
{
|
2015-02-28 11:16:21 -05:00
|
|
|
// DEBUG: LOGD("Setting hinge to right side");
|
2014-12-24 01:20:17 -05:00
|
|
|
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;
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
} ;
|