Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockDoor.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "BlockHandler.h"
5 #include "../BlockInfo.h"
6 #include "../Entities/Player.h"
7 #include "../Chunk.h"
8 #include "Mixins.h"
9 #include "ChunkInterface.h"
10 #include "BlockSlab.h"
11 
12 
13 
14 
15 
16 class cBlockDoorHandler final :
17  public cYawRotator<cBlockHandler, 0x03, 0x03, 0x00, 0x01, 0x02>
18 {
20 
21 public:
22 
23  using Super::Super;
24 
26  static bool CanBeOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
27  {
28  // Vanilla refuses to place doors on transparent blocks, except top-half slabs and other doors
29  // We need to keep the door compatible with itself, otherwise the top half drops while the bottom half stays
30 
31  // Doors can be placed on upside-down slabs
32  if (cBlockSlabHandler::IsAnySlabType(a_BlockType) && ((a_BlockMeta & 0x08) != 0))
33  {
34  return true;
35  }
36  // Doors can also be placed on other doors
37  else if (IsDoorBlockType(a_BlockType))
38  {
39  return true;
40  }
41  // Doors can not be placed on transparent blocks, but on any other block
42  else
43  {
44  return !cBlockInfo::IsTransparent(a_BlockType);
45  }
46  }
47 
50  {
51  switch (a_BlockMeta & 0x03)
52  {
53  case 0: return Vector3i(-1, 0, 0); // Facing West / XM
54  case 1: return Vector3i(0, 0, -1); // Facing North / ZM
55  case 2: return Vector3i(1, 0, 0); // Facing East / XP
56  default: return Vector3i(0, 0, 1); // Facing South / ZP
57  }
58  }
59 
61  inline static bool IsDoorBlockType(BLOCKTYPE a_Block)
62  {
63  switch (a_Block)
64  {
66  case E_BLOCK_BIRCH_DOOR:
68  case E_BLOCK_IRON_DOOR:
71  case E_BLOCK_OAK_DOOR:
72  {
73  return true;
74  }
75  default:
76  {
77  return false;
78  }
79  }
80  }
81 
84  static bool IsOpen(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos)
85  {
86  const auto Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockPos);
87  return (Meta & 0x04) != 0;
88  }
89 
91  static void SetOpen(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos, bool a_Open)
92  {
93  BLOCKTYPE Block = a_ChunkInterface.GetBlock(a_BlockPos);
94  if (!IsDoorBlockType(Block))
95  {
96  return;
97  }
98 
99  NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockPos);
100  bool IsOpened = ((Meta & 0x04) != 0);
101  if (IsOpened == a_Open)
102  {
103  return;
104  }
105 
106  // Change the door
107  NIBBLETYPE NewMeta = (Meta & 0x07) ^ 0x04; // Flip the "IsOpen" bit (0x04)
108  if ((Meta & 0x08) == 0)
109  {
110  // The block is the bottom part of the door
111  a_ChunkInterface.SetBlockMeta(a_BlockPos, NewMeta);
112  }
113  else
114  {
115  // The block is the top part of the door, set the meta to the corresponding top part
116  if (a_BlockPos.y > 0)
117  {
118  a_ChunkInterface.SetBlockMeta(a_BlockPos.addedY(-1), NewMeta);
119  }
120  }
121  }
122 
123 private:
124 
125  virtual void OnBroken(
126  cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
127  Vector3i a_BlockPos,
128  BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
129  const cEntity * a_Digger
130  ) const override;
131 
132  virtual bool OnUse(
133  cChunkInterface & a_ChunkInterface,
134  cWorldInterface & a_WorldInterface,
135  cPlayer & a_Player,
136  const Vector3i a_BlockPos,
137  eBlockFace a_BlockFace,
138  const Vector3i a_CursorPos
139  ) const override;
140 
141  virtual void OnCancelRightClick(
142  cChunkInterface & a_ChunkInterface,
143  cWorldInterface & a_WorldInterface,
144  cPlayer & a_Player,
145  const Vector3i a_BlockPos,
146  eBlockFace a_BlockFace
147  ) const override;
148 
149  virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override;
150  virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override;
151  virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override;
152  virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override;
153  virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override;
154 
155 
156 
157 
158 
159  virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
160  {
161  switch (m_BlockType)
162  {
170  default:
171  {
172  ASSERT(!"Unhandled door type!");
173  return {};
174  }
175  }
176  }
177 
178 
179 
180 
181 
182  virtual bool IsUseable(void) const override
183  {
184  return true;
185  }
186 
187 
188 
189 
190 
191  virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
192  {
193  // CanBeAt is also called on placement, so the top part can't check for the bottom part.
194  // Both parts can only that their base is a valid block.
195 
197  NIBBLETYPE BlockMeta;
198  const auto BasePosition = a_Position.addedY(((a_Meta & 0x8) == 0x8) ? -2 : -1);
199  a_Chunk.GetBlockTypeMeta(BasePosition, BlockType, BlockMeta);
200 
201  return (BasePosition.y >= 0) && CanBeOn(BlockType, BlockMeta);
202  }
203 
204 
205 
206 
207 
212  static NIBBLETYPE GetCompleteDoorMeta(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos)
213  {
214  NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
215 
216  if ((Meta & 0x08) != 0)
217  {
218  // The coords are pointing at the top part of the door
219  if (a_BlockPos.y > 0)
220  {
221  NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(-1));
222  return static_cast<NIBBLETYPE>((DownMeta & 0x07) | 0x08 | (Meta << 4));
223  }
224  // This is the top part of the door at the bottommost layer of the world, there's no bottom:
225  return static_cast<NIBBLETYPE>(0x08 | (Meta << 4));
226  }
227  else
228  {
229  // The coords are pointing at the bottom part of the door
230  if (a_BlockPos.y < cChunkDef::Height - 1)
231  {
232  NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(1));
233  return static_cast<NIBBLETYPE>(Meta | (UpMeta << 4));
234  }
235  // This is the bottom part of the door at the topmost layer of the world, there's no top:
236  return Meta;
237  }
238  }
239 
240 
241 
242 
243 
245  static void ChangeDoor(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos)
246  {
247  SetOpen(a_ChunkInterface, a_BlockPos, !IsOpen(a_ChunkInterface, a_BlockPos));
248  }
249 
250 
251 
252 
253 
254  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
255  {
256  UNUSED(a_Meta);
257  switch (m_BlockType)
258  {
259  case E_BLOCK_OAK_DOOR: return 13;
260  case E_BLOCK_SPRUCE_DOOR: return 34;
261  case E_BLOCK_BIRCH_DOOR: return 2;
262  case E_BLOCK_JUNGLE_DOOR: return 10;
263  case E_BLOCK_DARK_OAK_DOOR: return 26;
264  case E_BLOCK_ACACIA_DOOR: return 15;
265  case E_BLOCK_IRON_DOOR: return 6;
266  default:
267  {
268  ASSERT(!"Unhandled blocktype in door handler!");
269  return 0;
270  }
271  }
272  }
273 } ;
274 
275 
276 
277 
@ E_BLOCK_SPRUCE_DOOR
Definition: BlockType.h:212
@ E_BLOCK_BIRCH_DOOR
Definition: BlockType.h:213
@ E_BLOCK_IRON_DOOR
Definition: BlockType.h:85
@ E_BLOCK_JUNGLE_DOOR
Definition: BlockType.h:214
@ E_BLOCK_OAK_DOOR
Definition: BlockType.h:77
@ E_BLOCK_DARK_OAK_DOOR
Definition: BlockType.h:216
@ E_BLOCK_ACACIA_DOOR
Definition: BlockType.h:215
@ E_ITEM_ACACIA_DOOR
Definition: BlockType.h:477
@ E_ITEM_WOODEN_DOOR
Definition: BlockType.h:368
@ E_ITEM_DARK_OAK_DOOR
Definition: BlockType.h:478
@ E_ITEM_JUNGLE_DOOR
Definition: BlockType.h:476
@ E_ITEM_IRON_DOOR
Definition: BlockType.h:374
@ E_ITEM_BIRCH_DOOR
Definition: BlockType.h:475
@ E_ITEM_SPRUCE_DOOR
Definition: BlockType.h:474
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
Byte ColourID
Definition: Globals.h:162
#define ASSERT(x)
Definition: Globals.h:276
#define UNUSED
Definition: Globals.h:72
BlockType
Definition: BlockTypes.h:4
Vector3< int > Vector3i
Definition: Vector3.h:487
static bool IsTransparent(BLOCKTYPE Block)
Is a block transparent? (https://minecraft.wiki/w/Opacity)
Definition: BlockInfo.cpp:961
static void SetOpen(cChunkInterface &a_ChunkInterface, const Vector3i a_BlockPos, bool a_Open)
Sets the door to the specified state.
Definition: BlockDoor.h:91
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
Definition: BlockDoor.h:254
static NIBBLETYPE GetCompleteDoorMeta(cChunkInterface &a_ChunkInterface, const Vector3i a_BlockPos)
Returns the complete meta composed from the both parts of the door as (TopMeta << 4) | BottomMeta The...
Definition: BlockDoor.h:212
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override
Definition: BlockDoor.cpp:202
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override
Definition: BlockDoor.cpp:122
static void ChangeDoor(cChunkInterface &a_ChunkInterface, const Vector3i a_BlockPos)
Changes the door at the specified coords from open to close or vice versa.
Definition: BlockDoor.h:245
static bool IsOpen(cChunkInterface &a_ChunkInterface, const Vector3i a_BlockPos)
Returns true iff the door at the specified coords is open.
Definition: BlockDoor.h:84
virtual bool OnUse(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos) const override
Definition: BlockDoor.cpp:45
virtual void OnCancelRightClick(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace) const override
Definition: BlockDoor.cpp:92
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override
Definition: BlockDoor.cpp:150
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem *const a_Tool) const override
Definition: BlockDoor.h:159
static Vector3i GetRelativeDirectionToOutside(NIBBLETYPE a_BlockMeta)
Returns a vector pointing one block in the direction the door is facing (where the outside is).
Definition: BlockDoor.h:49
static bool IsDoorBlockType(BLOCKTYPE a_Block)
Returns true if the specified blocktype is any kind of door.
Definition: BlockDoor.h:61
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override
Definition: BlockDoor.cpp:168
virtual bool IsUseable(void) const override
Definition: BlockDoor.h:182
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override
Definition: BlockDoor.cpp:132
virtual bool CanBeAt(const cChunk &a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
Definition: BlockDoor.h:191
static bool CanBeOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Returns true if door can be placed on the specified block type.
Definition: BlockDoor.h:26
virtual void OnBroken(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity *a_Digger) const override
Definition: BlockDoor.cpp:10
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
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData)
Sets the meta for the specified block, while keeping the blocktype.
NIBBLETYPE GetBlockMeta(Vector3i a_Pos)
BLOCKTYPE GetBlock(Vector3i a_Pos)
Mixin for blocks whose meta on placement depends on the yaw of the player placing the block.
Definition: Mixins.h:162
cMetaRotator< cBlockHandler, BitMask, North, East, South, West, false > Super
Definition: Mixins.h:163
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Definition: Chunk.h:36
void GetBlockTypeMeta(Vector3i a_RelPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Definition: Chunk.cpp:1757
static const int Height
Definition: ChunkDef.h:125
Definition: Entity.h:76
Definition: Player.h:29
Definition: Item.h:37
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
Vector3< T > addedY(T a_AddY) const
Returns a copy of this vector moved by the specified amount on the y axis.
Definition: Vector3.h:314
T y
Definition: Vector3.h:17