diff options
Diffstat (limited to 'src/Items/ItemSlab.h')
-rw-r--r-- | src/Items/ItemSlab.h | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/Items/ItemSlab.h b/src/Items/ItemSlab.h new file mode 100644 index 000000000..1b68b9d0c --- /dev/null +++ b/src/Items/ItemSlab.h @@ -0,0 +1,93 @@ + +// ItemSlab.h + +// Declares the cItemSlabHandler responsible for handling slabs, when in their item form. + + + + + +#pragma once + +#include "ItemHandler.h" +#include "../Blocks/BlockSlab.h" + + + + + +class cItemSlabHandler: + public cItemHandler +{ + typedef cItemHandler super; + +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): + super(a_ItemType), + m_DoubleSlabBlockType(a_DoubleSlabBlockType) + { + } + + + // cItemHandler overrides: + 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 + ) override + { + // Special slab handling - placing a slab onto another slab produces a dblslab instead: + BLOCKTYPE ClickedBlockType; + NIBBLETYPE ClickedBlockMeta; + a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlockType, ClickedBlockMeta); + if ( + (ClickedBlockType == m_ItemType) && // Placing the same slab material + (ClickedBlockMeta == a_EquippedItem.m_ItemDamage) // Placing the same slab sub-kind (and existing slab is single) + ) + { + // If clicking the top side of a bottom-half slab, combine into a doubleslab: + if ( + (a_BlockFace == BLOCK_FACE_TOP) && + ((ClickedBlockMeta & 0x08) == 0) + ) + { + return a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, m_DoubleSlabBlockType, ClickedBlockMeta & 0x07); + } + + // If clicking the bottom side of a top-half slab, combine into a doubleslab: + if ( + (a_BlockFace == BLOCK_FACE_BOTTOM) && + ((ClickedBlockMeta & 0x08) != 0) + ) + { + return a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, m_DoubleSlabBlockType, ClickedBlockMeta & 0x07); + } + } + + // The slabs didn't combine, use the default handler to place the slab: + bool res = super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); + + /* + 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. + Ref.: http://forum.mc-server.org/showthread.php?tid=434&pid=17388#pid17388 + */ + if ((a_BlockFace == BLOCK_FACE_TOP) && (a_BlockY < cChunkDef::Height - 1)) + { + a_Player.SendBlocksAround(a_BlockX, a_BlockY + 1, a_BlockZ, 1); + } + return res; + } + +protected: + /** The block type to use when the slab combines into a doubleslab block. */ + BLOCKTYPE m_DoubleSlabBlockType; +}; + + + + |