Cuberite
A lightweight, fast and extensible game server for Minecraft
ItemSlab.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "ItemHandler.h"
5 
6 
7 
8 
9 
10 class cItemSlabHandler final:
11  public cItemHandler
12 {
14 
15 public:
16 
17  using Super::Super;
18 
19 private:
20 
21  virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override
22  {
23  // Confer BlockSlab.h, which we're in cahoots with to make the below logic work.
24 
25  // If clicking a slab, combine it into a double-slab:
26  if (cBlockSlabHandler::IsAnySlabType(a_Player.GetWorld()->GetBlock(a_PlacePosition)))
27  {
28  if (!a_Player.PlaceBlock(a_PlacePosition, GetDoubleSlabType(static_cast<BLOCKTYPE>(a_HeldItem.m_ItemType)), static_cast<NIBBLETYPE>(a_HeldItem.m_ItemDamage)))
29  {
30  return false;
31  }
32 
33  a_Player.SendBlocksAround(a_PlacePosition, 2); // (see below)
34  return true;
35  }
36 
37  // Set the correct metadata based on player equipped item:
38  if (!a_Player.PlaceBlock(a_PlacePosition, static_cast<BLOCKTYPE>(a_HeldItem.m_ItemType), FaceToMetaData(static_cast<NIBBLETYPE>(a_HeldItem.m_ItemDamage), a_ClickedBlockFace, a_CursorPosition)))
39  {
40  return false;
41  }
42 
43  /* This is a workaround for versions < 1.13, where the client combines a slab in the
44  direction of the clicked block face of a block ignoring build collision, rather than replacing said block.
45  Resend blocks to the client to fix the bug.
46  Ref.: https://forum.cuberite.org/thread-434-post-17388.html#pid17388 */
47  a_Player.SendBlocksAround(a_PlacePosition, 2);
48 
49  return true;
50  }
51 
52 
53  static NIBBLETYPE FaceToMetaData(const NIBBLETYPE a_BaseMeta, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition)
54  {
55  switch (a_ClickedBlockFace)
56  {
57  case BLOCK_FACE_TOP:
58  {
59  // Bottom half slab block:
60  return a_BaseMeta & 0x07;
61  }
62  case BLOCK_FACE_BOTTOM:
63  {
64  // Top half slab block:
65  return a_BaseMeta | 0x08;
66  }
67  case BLOCK_FACE_EAST:
68  case BLOCK_FACE_NORTH:
69  case BLOCK_FACE_SOUTH:
70  case BLOCK_FACE_WEST:
71  {
72  if (a_CursorPosition.y > 7)
73  {
74  // Cursor at top half of block, place top slab:
75  return a_BaseMeta | 0x08;
76  }
77  else
78  {
79  // Cursor at bottom half of block, place bottom slab:
80  return a_BaseMeta & 0x07;
81  }
82  }
83  default: UNREACHABLE("Unhandled block face");
84  }
85  }
86 
87 
89  static BLOCKTYPE GetDoubleSlabType(BLOCKTYPE a_SingleSlabBlockType)
90  {
91  switch (a_SingleSlabBlockType)
92  {
97  }
98  UNREACHABLE("Unhandled slab type");
99  }
100 };
@ E_BLOCK_DOUBLE_WOODEN_SLAB
Definition: BlockType.h:140
@ E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB
Definition: BlockType.h:200
@ E_BLOCK_STONE_SLAB
Definition: BlockType.h:54
@ E_BLOCK_DOUBLE_STONE_SLAB
Definition: BlockType.h:53
@ E_BLOCK_WOODEN_SLAB
Definition: BlockType.h:141
@ E_BLOCK_PURPUR_DOUBLE_SLAB
Definition: BlockType.h:223
@ E_BLOCK_PURPUR_SLAB
Definition: BlockType.h:224
@ E_BLOCK_RED_SANDSTONE_SLAB
Definition: BlockType.h:201
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
@ BLOCK_FACE_EAST
Definition: Defines.h:53
@ BLOCK_FACE_SOUTH
Definition: Defines.h:51
@ BLOCK_FACE_TOP
Definition: Defines.h:49
@ BLOCK_FACE_WEST
Definition: Defines.h:52
@ BLOCK_FACE_BOTTOM
Definition: Defines.h:48
@ BLOCK_FACE_NORTH
Definition: Defines.h:50
#define UNREACHABLE(x)
Definition: Globals.h:288
static bool IsAnySlabType(BLOCKTYPE a_BlockType)
Returns true if the specified blocktype is one of the slabs handled by this handler.
Definition: BlockSlab.h:30
cWorld * GetWorld(void) const
Definition: Entity.h:190
Definition: Player.h:29
void SendBlocksAround(Vector3i a_BlockPos, int a_Range=1)
Sends the block in the specified range around the specified coord to the client as a block change pac...
Definition: Player.cpp:2325
bool PlaceBlock(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Attempts to place the block in the world with a call to PlaceBlocks.
Definition: Player.cpp:2440
Definition: Item.h:37
short m_ItemType
Definition: Item.h:163
short m_ItemDamage
Definition: Item.h:165
constexpr cItemHandler(int a_ItemType)
Definition: ItemHandler.h:37
static NIBBLETYPE FaceToMetaData(const NIBBLETYPE a_BaseMeta, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition)
Definition: ItemSlab.h:53
virtual bool CommitPlacement(cPlayer &a_Player, const cItem &a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override
Performs the actual placement of this placeable item.
Definition: ItemSlab.h:21
static BLOCKTYPE GetDoubleSlabType(BLOCKTYPE a_SingleSlabBlockType)
Converts the single-slab blocktype to its equivalent double-slab blocktype.
Definition: ItemSlab.h:89
T y
Definition: Vector3.h:17
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363