2014-12-24 01:20:17 -05:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "ItemHandler.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cItemSlabHandler:
|
|
|
|
public cItemHandler
|
|
|
|
{
|
2020-04-13 12:38:06 -04:00
|
|
|
using Super = cItemHandler;
|
2014-12-24 01:20:17 -05:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** Creates a new handler for the specified slab item type.
|
|
|
|
Sets the handler to use the specified doubleslab block type for combining self into doubleslabs. */
|
|
|
|
cItemSlabHandler(int a_ItemType, BLOCKTYPE a_DoubleSlabBlockType):
|
2020-04-13 12:38:06 -04:00
|
|
|
Super(a_ItemType),
|
2014-12-24 01:20:17 -05:00
|
|
|
m_DoubleSlabBlockType(a_DoubleSlabBlockType)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-21 16:19:22 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
// cItemHandler overrides:
|
|
|
|
virtual bool OnPlayerPlace(
|
2020-04-21 16:19:22 -04:00
|
|
|
cWorld & a_World,
|
|
|
|
cPlayer & a_Player,
|
|
|
|
const cItem & a_EquippedItem,
|
|
|
|
const Vector3i a_ClickedBlockPos,
|
|
|
|
eBlockFace a_ClickedBlockFace,
|
|
|
|
const Vector3i a_CursorPos
|
2014-12-24 01:20:17 -05:00
|
|
|
) override
|
|
|
|
{
|
2020-04-21 16:19:22 -04:00
|
|
|
// If clicking a slab, try combining it into a double-slab:
|
2014-12-24 01:20:17 -05:00
|
|
|
BLOCKTYPE ClickedBlockType;
|
|
|
|
NIBBLETYPE ClickedBlockMeta;
|
2020-04-21 16:19:22 -04:00
|
|
|
a_World.GetBlockTypeMeta(a_ClickedBlockPos, ClickedBlockType, ClickedBlockMeta);
|
2014-12-24 01:20:17 -05:00
|
|
|
if (
|
2015-03-28 05:43:59 -04:00
|
|
|
(ClickedBlockType == m_ItemType) && // Placing the same slab material
|
|
|
|
((ClickedBlockMeta & 0x07) == a_EquippedItem.m_ItemDamage) // Placing the same slab sub-kind (and existing slab is single)
|
2014-12-24 01:20:17 -05:00
|
|
|
)
|
|
|
|
{
|
|
|
|
if (
|
2020-04-21 16:19:22 -04:00
|
|
|
((a_ClickedBlockFace == BLOCK_FACE_TOP) && ((ClickedBlockMeta & 0x08) == 0)) || // Top side of a bottom-half-slab
|
|
|
|
((a_ClickedBlockFace == BLOCK_FACE_BOTTOM) && ((ClickedBlockMeta & 0x08) != 0)) // Bottom side of a top-half-slab
|
2014-12-24 01:20:17 -05:00
|
|
|
)
|
|
|
|
{
|
2020-04-21 16:19:22 -04:00
|
|
|
if (!a_Player.PlaceBlock(a_ClickedBlockPos.x, a_ClickedBlockPos.y, a_ClickedBlockPos.z, m_DoubleSlabBlockType, ClickedBlockMeta & 0x07))
|
2015-11-09 15:12:32 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (a_Player.IsGameModeSurvival())
|
|
|
|
{
|
|
|
|
a_Player.GetInventory().RemoveOneEquippedItem();
|
|
|
|
}
|
|
|
|
return true;
|
2014-12-24 01:20:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-21 16:19:22 -04:00
|
|
|
// If there's already a slab in the destination, combine it into a double-slab:
|
|
|
|
auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
|
2015-04-07 18:16:10 -04:00
|
|
|
BLOCKTYPE PlaceBlockType;
|
|
|
|
NIBBLETYPE PlaceBlockMeta;
|
2020-04-21 16:19:22 -04:00
|
|
|
a_World.GetBlockTypeMeta(PlacePos, PlaceBlockType, PlaceBlockMeta);
|
2015-04-07 18:16:10 -04:00
|
|
|
if (
|
|
|
|
(PlaceBlockType == m_ItemType) && // Placing the same slab material
|
|
|
|
((PlaceBlockMeta & 0x07) == a_EquippedItem.m_ItemDamage) // Placing the same slab sub-kind (and existing slab is single)
|
|
|
|
)
|
|
|
|
{
|
2020-04-21 16:19:22 -04:00
|
|
|
if (!a_Player.PlaceBlock(PlacePos.x, PlacePos.y, PlacePos.z, m_DoubleSlabBlockType, PlaceBlockMeta & 0x07))
|
2015-11-09 15:12:32 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (a_Player.IsGameModeSurvival())
|
|
|
|
{
|
|
|
|
a_Player.GetInventory().RemoveOneEquippedItem();
|
|
|
|
}
|
|
|
|
return true;
|
2015-04-07 18:16:10 -04:00
|
|
|
}
|
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
// The slabs didn't combine, use the default handler to place the slab:
|
2020-04-21 16:19:22 -04:00
|
|
|
bool res = Super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_ClickedBlockPos, a_ClickedBlockFace, a_CursorPos);
|
2014-12-24 01:20:17 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
The client has a bug when a slab replaces snow and there's a slab above it.
|
|
|
|
The client then combines the slab above, rather than replacing the snow.
|
|
|
|
We send the block above the currently placed block back to the client to fix the bug.
|
2016-01-30 19:25:03 -05:00
|
|
|
Ref.: https://forum.cuberite.org/thread-434-post-17388.html#pid17388
|
2014-12-24 01:20:17 -05:00
|
|
|
*/
|
2020-04-21 16:19:22 -04:00
|
|
|
if ((a_ClickedBlockFace == BLOCK_FACE_TOP) && (a_ClickedBlockPos.y < cChunkDef::Height - 1))
|
2014-12-24 01:20:17 -05:00
|
|
|
{
|
2020-04-21 16:19:22 -04:00
|
|
|
auto AbovePos = a_ClickedBlockPos.addedY(1);
|
|
|
|
a_Player.SendBlocksAround(AbovePos.x, AbovePos.y, AbovePos.z, 1);
|
2014-12-24 01:20:17 -05:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-04-21 16:19:22 -04:00
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
protected:
|
2020-04-21 16:19:22 -04:00
|
|
|
|
2014-12-24 01:20:17 -05:00
|
|
|
/** The block type to use when the slab combines into a doubleslab block. */
|
|
|
|
BLOCKTYPE m_DoubleSlabBlockType;
|
|
|
|
};
|