Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockCactus.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "BlockPlant.h"
4 #include "../BlockInfo.h"
5 
6 
7 
8 
9 
10 class cBlockCactusHandler final :
11  public cClearMetaOnDrop<cBlockPlant<false>>
12 {
14 
15 public:
16 
17  using Super::Super;
18 
19 private:
20 
21  virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
22  {
23  if (a_Position.y <= 0)
24  {
25  return false;
26  }
27  BLOCKTYPE Surface = a_Chunk.GetBlock(a_Position.addedY(-1));
28  if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS))
29  {
30  // Cactus can only be placed on sand and itself
31  return false;
32  }
33 
34  // Check surroundings. Cacti may ONLY be surrounded by non-solid blocks
35  static const Vector3i Coords[] =
36  {
37  {-1, 0, 0},
38  { 1, 0, 0},
39  { 0, 0, -1},
40  { 0, 0, 1},
41  };
42  for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
43  {
45  NIBBLETYPE BlockMeta;
46  if (
47  a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta) &&
48  (
50  (BlockType == E_BLOCK_LAVA) ||
52  )
53  )
54  {
55  return false;
56  }
57  } // for i - Coords[]
58 
59  return true;
60  }
61 
62 
63 
64 
65 
66  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
67  {
68  UNUSED(a_Meta);
69  return 7;
70  }
71 
72 
73 
74 
75  virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
76  {
77  // Check the total height of the cacti blocks here:
78  int top = a_RelPos.y + 1;
79  while (
80  (top < cChunkDef::Height) &&
81  (a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_CACTUS)
82  )
83  {
84  ++top;
85  }
86  int bottom = a_RelPos.y - 1;
87  while (
88  (bottom > 0) &&
89  (a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_CACTUS)
90  )
91  {
92  --bottom;
93  }
94 
95  // Refuse if already too high:
96  auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (top - bottom));
97  if (numToGrow <= 0)
98  {
99  return 0;
100  }
101 
102  BLOCKTYPE blockType;
103  for (int i = 0; i < numToGrow; ++i)
104  {
105  Vector3i pos(a_RelPos.x, top + i, a_RelPos.z);
106  if (!a_Chunk.UnboundedRelGetBlockType(pos, blockType) || (blockType != E_BLOCK_AIR))
107  {
108  // Cannot grow there
109  return i;
110  }
111 
112  a_Chunk.UnboundedRelFastSetBlock(pos, E_BLOCK_CACTUS, 0);
113 
114  // Check surroundings. Cacti may ONLY be surrounded by non-solid blocks; if they aren't, drop as pickup and bail out the growing
115  static const Vector3i neighborOffsets[] =
116  {
117  {-1, 0, 0},
118  { 1, 0, 0},
119  { 0, 0, -1},
120  { 0, 0, 1},
121  } ;
122  for (const auto & ofs: neighborOffsets)
123  {
124  if (
125  a_Chunk.UnboundedRelGetBlockType(pos + ofs, blockType) &&
126  (
127  cBlockInfo::IsSolid(blockType) ||
128  (blockType == E_BLOCK_LAVA) ||
129  (blockType == E_BLOCK_STATIONARY_LAVA)
130  )
131  )
132  {
133  // Remove the cactus
134  auto absPos = a_Chunk.RelativeToAbsolute(pos);
135  a_Chunk.GetWorld()->DropBlockAsPickups(absPos);
136  return i + 1;
137  }
138  } // for neighbor
139  } // for i - numToGrow
140  return numToGrow;
141  }
142 
143  virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override
144  {
145  // Only allow growing if there's an air block above:
146  if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR))
147  {
148  return Super::CanGrow(a_Chunk, a_RelPos);
149  }
150  return paStay;
151  }
152 } ;
153 
154 
155 
156 
@ E_BLOCK_STATIONARY_LAVA
Definition: BlockType.h:21
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_CACTUS
Definition: BlockType.h:95
@ E_BLOCK_SAND
Definition: BlockType.h:22
@ E_BLOCK_LAVA
Definition: BlockType.h:20
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
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:231
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
virtual PlantAction CanGrow(cChunk &a_Chunk, Vector3i a_RelPos) const override
Checks whether a plant can grow grow, based on what is returned from cBlockPlant::HasEnoughLight and ...
Definition: BlockCactus.h:143
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: BlockCactus.h:66
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: BlockCactus.h:21
virtual int Grow(cChunk &a_Chunk, Vector3i a_RelPos, int a_NumStages=1) const override
Grows this block, if it supports growing, by the specified amount of stages (at most).
Definition: BlockCactus.h:75
virtual PlantAction CanGrow(cChunk &a_Chunk, Vector3i a_RelPos) const
Checks whether a plant can grow grow, based on what is returned from cBlockPlant::HasEnoughLight and ...
Definition: BlockPlant.h:81
cBlockHandler Super
Definition: BlockPlant.h:15
PlantAction
The action the plant can take on an update.
Definition: BlockPlant.h:27
Mixin to clear the block's meta value when converting to a pickup.
Definition: Mixins.h:31
Definition: Chunk.h:36
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
bool UnboundedRelFastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap...
Definition: Chunk.cpp:1156
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
cWorld * GetWorld(void) const
Definition: Chunk.h:135
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 const int Height
Definition: ChunkDef.h:125
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 x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
bool DropBlockAsPickups(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Digs the specified block, and spawns the appropriate pickups for it.
Definition: World.cpp:2090
int GetMaxCactusHeight(void) const
Definition: World.h:859