Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockVines.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "BlockHandler.h"
4 
5 
6 
7 
8 
9 class cBlockVinesHandler final :
10  public cBlockHandler
11 {
13 
14 public:
15 
16  using Super::Super;
17 
18 private:
19 
20  static const NIBBLETYPE VINE_LOST_SUPPORT = 16;
21  static const NIBBLETYPE VINE_UNCHANGED = 17;
22 
23 
24  virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
25  {
26  return GetMaxMeta(a_Chunk, a_Position, a_Meta) != VINE_LOST_SUPPORT;
27  }
28 
29 
30  virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
31  {
32  // Only drops self when using shears, otherwise drops nothing:
33  if ((a_Tool == nullptr) || (a_Tool->m_ItemType != E_ITEM_SHEARS))
34  {
35  return {};
36  }
37  return cItem(E_BLOCK_VINES, 1, 0);
38  }
39 
40 
41 
42 
43 
44  static char MetaDataToDirection(NIBBLETYPE a_MetaData)
45  {
46  switch (a_MetaData)
47  {
48  case 0x1: return BLOCK_FACE_NORTH;
49  case 0x4: return BLOCK_FACE_SOUTH;
50  case 0x8: return BLOCK_FACE_WEST;
51  case 0x2: return BLOCK_FACE_EAST;
52  default: return BLOCK_FACE_TOP;
53  }
54  }
55 
56 
57 
58 
59 
61  static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
62  {
63  switch (a_BlockType)
64  {
65  case E_BLOCK_CHEST:
67  case E_BLOCK_GLASS:
68  case E_BLOCK_PISTON:
75  {
76  // You can't attach a vine to this solid blocks.
77  return false;
78  }
79  default:
80  {
81  return cBlockInfo::IsSolid(a_BlockType);
82  }
83  }
84  }
85 
86 
87 
88 
89 
92  static NIBBLETYPE GetMaxMeta(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta)
93  {
94  static const struct
95  {
96  int x, z;
97  NIBBLETYPE Bit;
98  } Coords[] =
99  {
100  { 0, 1, 1}, // south, ZP
101  {-1, 0, 2}, // west, XM
102  { 0, -1, 4}, // north, ZM
103  { 1, 0, 8}, // east, XP
104  } ;
105 
106  NIBBLETYPE MaxMeta = 0;
107  for (auto & Coord : Coords)
108  {
110  NIBBLETYPE BlockMeta;
111  auto checkPos = a_Position.addedXZ(Coord.x, Coord.z);
112  if (
113  a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) &&
115  )
116  {
117  MaxMeta |= Coord.Bit;
118  }
119  }
120 
121  // Check if vine above us, add its meta to MaxMeta:
122  if ((a_Position.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_Position.addedY(1)) == E_BLOCK_VINES))
123  {
124  MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1));
125  }
126 
127  NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal.
128  if (Common != a_CurrentMeta)
129  {
130  bool HasTop = (a_Position.y < (cChunkDef::Height - 1)) && IsBlockAttachable(a_Chunk.GetBlock(a_Position.addedY(1)));
131  if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine.
132  {
133  return VINE_LOST_SUPPORT;
134  }
135 
136  return Common;
137  }
138 
139  return VINE_UNCHANGED;
140  }
141 
142 
143 
144 
145 
146  virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override
147  {
148  a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk)
149  {
150 
151  const auto Position = cChunkDef::AbsoluteToRelative(a_BlockPos);
152  const auto MaxMeta = GetMaxMeta(a_Chunk, Position, a_Chunk.GetMeta(Position));
153 
154  if (MaxMeta == VINE_UNCHANGED)
155  {
156  return false;
157  }
158 
159  // There is a neighbor missing, need to update the meta or even destroy the block.
160 
161  if (MaxMeta == VINE_LOST_SUPPORT)
162  {
163  // The vine just lost all its support, destroy the block:
164  a_Chunk.SetBlock(Position, E_BLOCK_AIR, 0);
165  }
166  else
167  {
168  // It lost some of its support, set it to what remains (SetBlock to notify neighbors):
169  a_Chunk.SetBlock(Position, E_BLOCK_VINES, MaxMeta);
170  }
171 
172  return false;
173  });
174  }
175 
176 
177 
178 
179 
180  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
181  {
182  return !a_ClickedDirectly || (a_HeldItem.m_ItemType != m_BlockType);
183  }
184 
185 
186 
187 
188 
189  virtual void OnUpdate(
190  cChunkInterface & a_ChunkInterface,
191  cWorldInterface & a_WorldInterface,
192  cBlockPluginInterface & a_PluginInterface,
193  cChunk & a_Chunk,
194  const Vector3i a_RelPos
195  ) const override
196  {
197  UNUSED(a_ChunkInterface);
198  UNUSED(a_WorldInterface);
199 
200  // Vine cannot grow down if at the bottom:
201  auto GrowPos = a_RelPos.addedY(-1);
202  if (!cChunkDef::IsValidHeight(GrowPos))
203  {
204  return;
205  }
206 
207  // Grow one block down, if possible:
209  a_Chunk.UnboundedRelGetBlockType(GrowPos, Block);
210  if (Block == E_BLOCK_AIR)
211  {
212  auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos);
213  if (!a_PluginInterface.CallHookBlockSpread(WorldPos, ssVineSpread))
214  {
215  a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos));
216  }
217  }
218  }
219 
220 
221 
222 
223 
224  virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override
225  {
226  return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right
227  }
228 
229 
230 
231 
232 
233  virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override
234  {
235  return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left
236  }
237 
238 
239 
240 
241 
242  virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override
243  {
244  // Bits 2 and 4 stay, bits 1 and 3 swap
245  return static_cast<NIBBLETYPE>((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2));
246  }
247 
248 
249 
250 
251 
252  virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override
253  {
254  // Bits 1 and 3 stay, bits 2 and 4 swap
255  return static_cast<NIBBLETYPE>((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
256  }
257 
258 
259 
260 
261 
262  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
263  {
264  UNUSED(a_Meta);
265  return 7;
266  }
267 } ;
268 
269 
270 
271 
@ E_BLOCK_STAINED_GLASS
Definition: BlockType.h:110
@ E_BLOCK_REDSTONE_REPEATER_ON
Definition: BlockType.h:109
@ E_BLOCK_STICKY_PISTON
Definition: BlockType.h:39
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_PISTON_EXTENSION
Definition: BlockType.h:44
@ E_BLOCK_CHEST
Definition: BlockType.h:64
@ E_BLOCK_TRAPPED_CHEST
Definition: BlockType.h:161
@ E_BLOCK_VINES
Definition: BlockType.h:121
@ E_BLOCK_REDSTONE_REPEATER_OFF
Definition: BlockType.h:108
@ E_BLOCK_ENDER_CHEST
Definition: BlockType.h:145
@ E_BLOCK_GLASS
Definition: BlockType.h:30
@ E_BLOCK_PISTON
Definition: BlockType.h:43
@ E_ITEM_SHEARS
Definition: BlockType.h:404
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_NORTH
Definition: Defines.h:50
@ ssVineSpread
Definition: Defines.h:344
Byte ColourID
Definition: Globals.h:162
#define UNUSED
Definition: Globals.h:72
BlockType
Definition: BlockTypes.h:4
static bool IsSolid(BLOCKTYPE Block)
Is this block solid (player cannot walk through)?
Definition: BlockInfo.cpp:892
constexpr cBlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockHandler.h:29
const BLOCKTYPE m_BlockType
Definition: BlockHandler.h:205
This interface is used to decouple block handlers from the cPluginManager dependency through cWorld.
virtual bool CallHookBlockSpread(Vector3i a_BlockPos, eSpreadSource a_Source)=0
static NIBBLETYPE GetMaxMeta(const cChunk &a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta)
Returns the meta that has the maximum allowable sides of the vine, given the surroundings and current...
Definition: BlockVines.h:92
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override
Mirros a given block meta around the YZ plane.
Definition: BlockVines.h:252
static const NIBBLETYPE VINE_LOST_SUPPORT
Definition: BlockVines.h:20
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override
Rotates a given block meta clockwise.
Definition: BlockVines.h:233
virtual bool CanBeAt(const cChunk &a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
Checks if the block can stay at the specified relative coords in the chunk.
Definition: BlockVines.h:24
static const NIBBLETYPE VINE_UNCHANGED
Definition: BlockVines.h:21
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: BlockVines.h:262
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
Returns true if the specified block type is good for vines to attach to.
Definition: BlockVines.h:61
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override
Rotates a given block meta counter-clockwise.
Definition: BlockVines.h:224
virtual void OnNeighborChanged(cChunkInterface &a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override
Called when a direct neighbor of this block has been changed.
Definition: BlockVines.h:146
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: BlockVines.h:30
static char MetaDataToDirection(NIBBLETYPE a_MetaData)
Definition: BlockVines.h:44
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: BlockVines.h:180
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override
Mirrors a given block meta around the XY plane.
Definition: BlockVines.h:242
virtual void OnUpdate(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cBlockPluginInterface &a_PluginInterface, cChunk &a_Chunk, const Vector3i a_RelPos) const override
Called when the block gets ticked either by a random tick or by a queued tick.
Definition: BlockVines.h:189
bool DoWithChunkAt(Vector3i a_BlockPos, cFunctionRef< bool(cChunk &)> a_Callback)
Definition: Chunk.h:36
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:279
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:146
Vector3i RelativeToAbsolute(Vector3i a_RelBlockPosition) const
Converts the coord relative to this chunk into an absolute coord.
Definition: Chunk.h:450
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: Chunk.cpp:1263
bool UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in ...
Definition: Chunk.cpp:1135
bool UnboundedRelGetBlock(Vector3i a_RelCoords, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in ...
Definition: Chunk.cpp:1008
bool UnboundedRelGetBlockType(Vector3i a_RelCoords, BLOCKTYPE &a_BlockType) const
Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap...
Definition: Chunk.cpp:1029
static bool IsValidHeight(Vector3i a_BlockPosition)
Validates a height-coordinate.
Definition: ChunkDef.h:185
static void AbsoluteToRelative(int &a_X, int &a_Y, int &a_Z, int &a_ChunkX, int &a_ChunkZ)
Converts absolute block coords into relative (chunk + block) coords:
Definition: ChunkDef.h:147
static const int Height
Definition: ChunkDef.h:125
Definition: Item.h:37
short m_ItemType
Definition: Item.h:163
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
Vector3< T > addedXZ(T a_AddX, T a_AddZ) const
Returns a copy of this vector moved by the specified amount on the X and Z axes.
Definition: Vector3.h:326
T y
Definition: Vector3.h:17
Definition: World.h:53