Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockSlab.h
Go to the documentation of this file.
1 
2 // BlockSlab.h
3 
4 // Declares cBlockSlabHandler and cBlockDoubleSlabHandler classes
5 
6 
7 
8 
9 
10 #pragma once
11 
12 #include "BlockHandler.h"
13 #include "ChunkInterface.h"
14 #include "../BlockInfo.h"
15 #include "../Entities/Player.h"
16 #include "../BlockInfo.h"
17 
18 
19 
20 class cBlockSlabHandler final :
21  public cBlockHandler
22 {
24 
25 public:
26 
27  using Super::Super;
28 
30  static bool IsAnySlabType(BLOCKTYPE a_BlockType)
31  {
32  return (
33  (a_BlockType == E_BLOCK_WOODEN_SLAB) ||
34  (a_BlockType == E_BLOCK_STONE_SLAB) ||
35  (a_BlockType == E_BLOCK_RED_SANDSTONE_SLAB) ||
36  (a_BlockType == E_BLOCK_PURPUR_SLAB)
37  );
38  }
39 
40 private:
41 
42  virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
43  {
44  // Reset the "top half" flag:
45  return cItem(m_BlockType, 1, a_BlockMeta & 0x07);
46  }
47 
48 
49  virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override
50  {
51  /* Double slab combining uses build collision checks to replace single slabs with double slabs in the right conditions.
52  For us to be replaced, the player must be:
53  1. Placing the same slab material.
54  2. Placing the same slab sub-kind (and existing slab is single). */
55  if ((m_BlockType != a_HeldItem.m_ItemType) || ((a_Meta & 0x07) != a_HeldItem.m_ItemDamage))
56  {
57  return false;
58  }
59 
60  const bool IsTopSlab = (a_Meta & 0x08) == 0x08;
61  const auto CanClickCombine = ((a_ClickedBlockFace == BLOCK_FACE_TOP) && !IsTopSlab) || ((a_ClickedBlockFace == BLOCK_FACE_BOTTOM) && IsTopSlab);
62 
63  /* When the player clicks on us directly, we'll combine if we're
64  a bottom slab and he clicked the top, or vice versa. Clicking on the sides will not combine.
65  However, when indirectly clicked (on the side of another block, that caused placement to go to us)
66  the conditions are exactly the opposite. */
67  return a_ClickedDirectly ? CanClickCombine : !CanClickCombine;
68  }
69 
70 
71 
72 
73 
74  virtual void OnCancelRightClick(
75  cChunkInterface & a_ChunkInterface,
76  cWorldInterface & a_WorldInterface,
77  cPlayer & a_Player,
78  const Vector3i a_BlockPos,
79  eBlockFace a_BlockFace
80  ) const override
81  {
82  if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player.GetEquippedItem().m_ItemType != static_cast<short>(m_BlockType)))
83  {
84  return;
85  }
86 
87  // Sends the slab back to the client. It's to refuse a doubleslab placement. */
88  a_Player.GetWorld()->SendBlockTo(a_BlockPos, a_Player);
89  }
90 
91 
92 
93 
94 
95  virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override
96  {
97  // Toggle the 4th bit - up / down:
98  return (a_Meta ^ 0x08);
99  }
100 
101 
102 
103 
104 
105  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
106  {
107  a_Meta &= 0x7;
108 
109  switch (m_BlockType)
110  {
111  case E_BLOCK_STONE_SLAB:
112  {
113  switch (a_Meta)
114  {
115  case E_META_STONE_SLAB_SANDSTONE: return 2;
116  case E_META_STONE_SLAB_PLANKS: return 13;
119  case E_META_STONE_SLAB_COBBLESTONE: return 11;
120  case E_META_STONE_SLAB_BRICK: return 28;
121  case E_META_STONE_SLAB_NETHER_BRICK: return 35;
122  case E_META_STONE_SLAB_QUARTZ: return 8;
123  default:
124  {
125  ASSERT(!"Unhandled meta in slab handler!");
126  return 0;
127  }
128  }
129  }
130  case E_BLOCK_WOODEN_SLAB:
131  {
132  switch (a_Meta)
133  {
134  case E_META_WOODEN_SLAB_BIRCH: return 2;
135  case E_META_WOODEN_SLAB_JUNGLE: return 10;
136  case E_META_WOODEN_SLAB_OAK: return 13;
137  case E_META_WOODEN_SLAB_ACACIA: return 15;
138  case E_META_WOODEN_SLAB_DARK_OAK: return 26;
139  case E_META_WOODEN_SLAB_SPRUCE: return 34;
140  default:
141  {
142  ASSERT(!"Unhandled meta in slab handler!");
143  return 0;
144  }
145  }
146  }
148  {
149  return 10;
150  }
151  case E_BLOCK_PURPUR_SLAB:
152  {
153  return 16;
154  }
155  default:
156  {
157  ASSERT(!"Unhandled blocktype in slab handler!");
158  return 0;
159  }
160  }
161  }
162 
163 
164 
165 
166 
167  virtual bool IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) const override
168  {
169  if (a_BlockMeta & 0x08) // top half
170  {
171  return true;
172  }
173  return cBlockHandler::IsInsideBlock(a_Position, a_BlockMeta);
174  }
175 } ;
176 
177 
178 
179 
180 
182  public cBlockHandler
183 {
185 
186 public:
187 
188  using Super::Super;
189 
190 private:
191 
192  virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
193  {
195  return cItem(Block, 2, a_BlockMeta & 0x7);
196  }
197 
198 
199 
200 
201 
202  inline static BLOCKTYPE GetSingleSlabType(BLOCKTYPE a_BlockType)
203  {
204  switch (a_BlockType)
205  {
210  }
211  ASSERT(!"Unhandled double slab type!");
212  return a_BlockType;
213  }
214 
215 
216 
217 
218 
219  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
220  {
221  // For doule slabs, the meta values are the same. Only the meaning of the 4th bit changes, but that's ignored in the below handler
223  }
224 } ;
225 
226 
227 
228 
@ E_META_WOODEN_SLAB_BIRCH
Definition: BlockType.h:985
@ E_META_STONE_SLAB_PLANKS
Definition: BlockType.h:916
@ E_META_WOODEN_SLAB_ACACIA
Definition: BlockType.h:987
@ E_META_STONE_SLAB_STONE
Definition: BlockType.h:914
@ E_META_WOODEN_SLAB_OAK
Definition: BlockType.h:983
@ E_META_STONE_SLAB_STONE_BRICK
Definition: BlockType.h:919
@ E_META_STONE_SLAB_BRICK
Definition: BlockType.h:918
@ E_META_WOODEN_SLAB_JUNGLE
Definition: BlockType.h:986
@ E_META_STONE_SLAB_NETHER_BRICK
Definition: BlockType.h:920
@ E_META_STONE_SLAB_QUARTZ
Definition: BlockType.h:921
@ E_META_WOODEN_SLAB_SPRUCE
Definition: BlockType.h:984
@ E_META_STONE_SLAB_COBBLESTONE
Definition: BlockType.h:917
@ E_META_WOODEN_SLAB_DARK_OAK
Definition: BlockType.h:988
@ E_META_STONE_SLAB_SANDSTONE
Definition: BlockType.h:915
@ 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_TOP
Definition: Defines.h:49
@ BLOCK_FACE_BOTTOM
Definition: Defines.h:48
@ BLOCK_FACE_NONE
Definition: Defines.h:39
Byte ColourID
Definition: Globals.h:162
#define ASSERT(x)
Definition: Globals.h:276
virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) const
Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the bloc...
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const
Returns the base colour ID of the block, as will be represented on a map, as per documentation: https...
static const cBlockHandler & For(BLOCKTYPE a_BlockType)
constexpr cBlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockHandler.h:29
const BLOCKTYPE m_BlockType
Definition: BlockHandler.h:205
virtual bool DoesIgnoreBuildCollision(const cWorld &a_World, const cItem &a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override
Checks if the player can build "inside" this block.
Definition: BlockSlab.h:49
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override
Mirros a given block meta around the XZ plane.
Definition: BlockSlab.h:95
virtual bool IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) const override
Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the bloc...
Definition: BlockSlab.h:167
virtual void OnCancelRightClick(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace) const override
Called when a right click to this block is cancelled.
Definition: BlockSlab.h:74
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
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
Returns the base colour ID of the block, as will be represented on a map, as per documentation: https...
Definition: BlockSlab.h:105
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem *const a_Tool) const override
Returns the pickups that would result if the block was mined by a_Digger using a_Tool.
Definition: BlockSlab.h:42
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem *const a_Tool) const override
Returns the pickups that would result if the block was mined by a_Digger using a_Tool.
Definition: BlockSlab.h:192
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
Returns the base colour ID of the block, as will be represented on a map, as per documentation: https...
Definition: BlockSlab.h:219
static BLOCKTYPE GetSingleSlabType(BLOCKTYPE a_BlockType)
Definition: BlockSlab.h:202
cWorld * GetWorld(void) const
Definition: Entity.h:190
Definition: Player.h:29
const cItem & GetEquippedItem(void) const
Definition: Player.h:162
Definition: Item.h:37
short m_ItemType
Definition: Item.h:163
short m_ItemDamage
Definition: Item.h:165
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
Definition: World.h:53
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer &a_Player) override
Sends the block at the specified coords to the player.
Definition: World.cpp:2114