Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockTorch.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "BlockHandler.h"
4 #include "../Chunk.h"
5 #include "ChunkInterface.h"
6 #include "Mixins.h"
7 
8 
9 
10 
12  public cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>>
13 {
15 
16 public:
17 
19  super(a_BlockType)
20  {
21  }
22 
24  cChunkInterface & a_ChunkInterface, cPlayer & a_Player,
25  int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
26  int a_CursorX, int a_CursorY, int a_CursorZ,
27  BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
28  ) override
29  {
30  BLOCKTYPE Block;
31  NIBBLETYPE Meta;
32  AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
33  a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY, a_BlockZ}, Block, Meta);
34 
35  if (!CanBePlacedOn(Block, Meta, a_BlockFace)) // Try to preserve original direction
36  {
37  // Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
38 
39  AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
40  a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Set a_BlockFace to a valid direction which will be converted later to a metadata
41  if (a_BlockFace == BLOCK_FACE_NONE)
42  {
43  // No attachable face found - don't place the torch
44  return false;
45  }
46  }
47 
48  a_BlockType = m_BlockType;
49  a_BlockMeta = DirectionToMetaData(a_BlockFace);
50  return true;
51  }
52 
53  inline static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction)
54  {
55  switch (a_Direction)
56  {
57  case BLOCK_FACE_BOTTOM: ASSERT(!"Shouldn't be getting this face"); return 0;
63  case BLOCK_FACE_NONE:
64  {
65  ASSERT(!"Unhandled torch direction!");
66  break;
67  }
68  }
69  return 0x0;
70  }
71 
72  inline static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData)
73  {
74  switch (a_MetaData)
75  {
76  case 0: return BLOCK_FACE_TOP; // By default, the torches stand on the ground
82  default:
83  {
84  ASSERT(!"Unhandled torch metadata");
85  break;
86  }
87  }
88  return BLOCK_FACE_TOP;
89  }
90 
91  static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace)
92  {
93  switch (a_BlockType)
94  {
96  case E_BLOCK_SOULSAND:
97  {
98  // Exceptional vanilla behaviour
99  return true;
100  }
101  case E_BLOCK_GLASS:
103  case E_BLOCK_FENCE:
106  case E_BLOCK_BIRCH_FENCE:
111  {
112  // Torches can only be placed on top of these blocks
113  return (a_BlockFace == BLOCK_FACE_YP);
114  }
115  case E_BLOCK_STONE_SLAB:
116  case E_BLOCK_WOODEN_SLAB:
117  {
118  // Toches can be placed on the top of these slabs only if the occupy the top half of the voxel
119  return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08));
120  }
134  {
135  return (a_BlockFace == BLOCK_FACE_TOP) && (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN);
136  }
137  default:
138  {
139  if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
140  {
141  // Torches can be placed on all sides of full blocks except the bottom
142  return (a_BlockFace != BLOCK_FACE_YM);
143  }
144  return false;
145  }
146  }
147  }
148 
150  static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
151  {
152  for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all directions
153  {
154  eBlockFace Face = static_cast<eBlockFace>(i);
155  AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, true);
156  BLOCKTYPE BlockInQuestion;
157  NIBBLETYPE BlockInQuestionMeta;
158  a_ChunkInterface.GetBlockTypeMeta({a_BlockX, a_BlockY, a_BlockZ}, BlockInQuestion, BlockInQuestionMeta);
159 
160  if (CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face))
161  {
162  return Face;
163  }
164  else
165  {
166  // Reset coords in preparation for next iteration
167  AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, false);
168  }
169  }
170  return BLOCK_FACE_NONE;
171  }
172 
173  virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
174  {
175  eBlockFace Face = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
176  AddFaceDirection(a_RelX, a_RelY, a_RelZ, Face, true);
177 
178  BLOCKTYPE BlockInQuestion;
179  NIBBLETYPE BlockInQuestionMeta;
180  if (!a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockInQuestion, BlockInQuestionMeta))
181  {
182  return false;
183  }
184 
185  return CanBePlacedOn(BlockInQuestion, BlockInQuestionMeta, Face);
186  }
187 
188  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
189  {
190  UNUSED(a_Meta);
191  return 0;
192  }
193 } ;
194 
195 
196 
197 
virtual bool GetPlacementBlockTypeMeta(cChunkInterface &a_ChunkInterface, cPlayer &a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) override
Called before a block is placed into a world.
Definition: BlockTorch.h:23
static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction)
Definition: BlockTorch.h:53
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
bool GetBlockTypeMeta(Vector3i a_Pos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
Definition: Player.h:27
virtual bool CanBeAt(cChunkInterface &a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk &a_Chunk) override
Checks if the block can stay at the specified relative coords in the chunk.
Definition: BlockTorch.h:173
BLOCKTYPE m_BlockType
Definition: BlockHandler.h:213
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
Returns the base colour ID of the block, as will be represented on a map, as per documentation: https...
Definition: BlockTorch.h:188
static eBlockFace FindSuitableFace(cChunkInterface &a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure.
Definition: BlockTorch.h:150
cBlockTorchHandler(BLOCKTYPE a_BlockType)
Definition: BlockTorch.h:18
Definition: Chunk.h:49
void AddFaceDirection(int &a_BlockX, int &a_BlockY, int &a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse=false)
Definition: Defines.h:859
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:380
#define ASSERT(x)
Definition: Globals.h:335
#define UNUSED
Definition: Globals.h:152
static bool FullyOccupiesVoxel(BLOCKTYPE a_Type)
Definition: BlockInfo.h:50
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc...
Definition: Defines.h:29
bool UnboundedRelGetBlock(Vector3i a_RelCoords, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Same as GetBlock(), but relative coords needn&#39;t be in this chunk (uses m_Neighbor-s or m_ChunkMap in ...
Definition: Chunk.cpp:997
Byte ColourID
Definition: Globals.h:118
static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData)
Definition: BlockTorch.h:72
Mixin to clear the block&#39;s meta value when converting to a pickup.
Definition: Mixins.h:55
static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace)
Definition: BlockTorch.h:91