Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockStems.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "BlockPlant.h"
5 
6 
7 
8 
9 
13 template <BLOCKTYPE ProduceBlockType, ENUM_ITEM_TYPE StemPickupType>
14 class cBlockStemsHandler final :
15  public cBlockPlant<true>
16 {
18 
19 public:
20 
21  using Super::Super;
22 
23 private:
24 
25  virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
26  {
27  /*
28  Use correct percent:
29  https://minecraft.wiki/w/Melon_Seeds#Breaking
30  https://minecraft.wiki/w/Pumpkin_Seeds#Breaking
31  */
32 
33  // Age > 7 (Impossible)
34  if (a_BlockMeta > 7)
35  {
36  return cItem(StemPickupType);
37  }
38 
39  const auto Threshold = GetRandomProvider().RandReal<double>(100);
40  double Cumulative = 0;
41  char Count = 0;
42 
43  for (; Count < 4; Count++)
44  {
45  Cumulative += m_AgeSeedDropProbability[static_cast<size_t>(a_BlockMeta)][static_cast<size_t>(Count)];
46  if (Cumulative > Threshold)
47  {
48  break;
49  }
50  }
51 
52  return cItem(StemPickupType, Count);
53  }
54 
55 
56 
57 
58 
59  virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
60  {
61  return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND);
62  }
63 
64 
65 
66 
67 
68  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
69  {
70  UNUSED(a_Meta);
71  return 7;
72  }
73 
74 
75 
76 
77 
78  virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
79  {
80  const auto OldMeta = a_Chunk.GetMeta(a_RelPos);
81  const auto NewMeta = std::clamp<NIBBLETYPE>(static_cast<NIBBLETYPE>(OldMeta + a_NumStages), 0, 7);
82  a_Chunk.SetMeta(a_RelPos, NewMeta);
83  return NewMeta - OldMeta;
84  }
85 
86 
87 
88 
89 
90  virtual void BearFruit(cChunk & a_Chunk, const Vector3i a_StemRelPos) const override
91  {
92  auto & Random = GetRandomProvider();
93 
94  // Check if there's another produce around the stem, if so, abort:
95  static constexpr std::array<Vector3i, 4> NeighborOfs =
96  {
97  {
98  { 1, 0, 0},
99  {-1, 0, 0},
100  { 0, 0, 1},
101  { 0, 0, -1},
102  }
103  };
104 
105  std::array<BLOCKTYPE, 4> BlockType;
106  if (
107  !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[0], BlockType[0]) ||
108  !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[1], BlockType[1]) ||
109  !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[2], BlockType[2]) ||
110  !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[3], BlockType[3]) ||
111  (BlockType[0] == ProduceBlockType) ||
112  (BlockType[1] == ProduceBlockType) ||
113  (BlockType[2] == ProduceBlockType) ||
114  (BlockType[3] == ProduceBlockType)
115  )
116  {
117  // Neighbors not valid or already taken by the same produce:
118  return;
119  }
120 
121  // Pick a direction in which to place the produce:
122  int x = 0, z = 0;
123  const auto CheckType = Random.RandInt<size_t>(3); // The index to the neighbors array which should be checked for emptiness
124  switch (CheckType)
125  {
126  case 0: x = 1; break;
127  case 1: x = -1; break;
128  case 2: z = 1; break;
129  case 3: z = -1; break;
130  }
131 
132  // Check that the block in that direction is empty:
133  switch (BlockType[CheckType])
134  {
135  case E_BLOCK_AIR:
136  case E_BLOCK_SNOW:
137  case E_BLOCK_TALL_GRASS:
138  case E_BLOCK_DEAD_BUSH:
139  {
140  break;
141  }
142  default: return;
143  }
144 
145  // Check if there's soil under the neighbor. We already know the neighbors are valid. Place produce if ok
146  BLOCKTYPE SoilType;
147  const auto ProduceRelPos = a_StemRelPos + Vector3i(x, 0, z);
148  VERIFY(a_Chunk.UnboundedRelGetBlockType(ProduceRelPos.addedY(-1), SoilType));
149 
150  switch (SoilType)
151  {
152  case E_BLOCK_DIRT:
153  case E_BLOCK_GRASS:
154  case E_BLOCK_FARMLAND:
155  {
156  const NIBBLETYPE Meta = (ProduceBlockType == E_BLOCK_MELON) ? 0 : static_cast<NIBBLETYPE>(Random.RandInt(4) % 4);
157 
158  FLOGD("Growing melon / pumpkin at {0} (<{1}, {2}> from stem), overwriting {3}, growing on top of {4}, meta {5}",
159  a_Chunk.RelativeToAbsolute(ProduceRelPos),
160  x, z,
161  ItemTypeToString(BlockType[CheckType]),
162  ItemTypeToString(SoilType),
163  Meta
164  );
165 
166  // Place a randomly-facing produce:
167  a_Chunk.SetBlock(ProduceRelPos, ProduceBlockType, Meta);
168  }
169  }
170  }
171 
172 private:
173 
174  // https://minecraft.wiki/w/Pumpkin_Seeds#Breaking
175  // https://minecraft.wiki/w/Melon_Seeds#Breaking
178  static constexpr std::array<std::array<double, 4>, 8> m_AgeSeedDropProbability
179  {
180  {
181  {
182  81.3, 17.42, 1.24, 0.03
183  },
184  {
185  65.1, 30.04, 4.62, 0.24
186  },
187  {
188  51.2, 38.4, 9.6, 0.8
189  },
190  {
191  39.44, 43.02, 15.64, 1.9
192  },
193  {
194  29.13, 44.44, 22.22, 3.7
195  },
196  {
197  21.6, 43.2, 28.8, 6.4
198  },
199  {
200  15.17, 39.82, 34.84, 10.16
201  },
202  {
203  10.16, 34.84, 39.82, 15.17
204  }
205  }
206  };
207 } ;
208 
AString ItemTypeToString(short a_ItemType)
Translates itemtype into a string.
Definition: BlockType.cpp:252
@ E_BLOCK_DEAD_BUSH
Definition: BlockType.h:42
@ E_BLOCK_FARMLAND
Definition: BlockType.h:72
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_GRASS
Definition: BlockType.h:12
@ E_BLOCK_MELON
Definition: BlockType.h:118
@ E_BLOCK_SNOW
Definition: BlockType.h:92
@ E_BLOCK_DIRT
Definition: BlockType.h:13
@ E_BLOCK_TALL_GRASS
Definition: BlockType.h:41
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
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
Byte ColourID
Definition: Globals.h:162
#define VERIFY(x)
Definition: Globals.h:280
#define UNUSED
Definition: Globals.h:72
#define FLOGD
Definition: LoggerSimple.h:91
BlockType
Definition: BlockTypes.h:4
Vector3< int > Vector3i
Definition: Vector3.h:487
Base class for plants that use light values to decide whether to grow or not.
Definition: BlockPlant.h:14
cBlockHandler Super
Definition: BlockPlant.h:15
Handler for stems from which produce grows in an adjacent block (melon, pumpkin) after it becomes rip...
Definition: BlockStems.h:16
static constexpr std::array< std::array< double, 4 >, 8 > m_AgeSeedDropProbability
The array describes how many seed may be dropped at which age.
Definition: BlockStems.h:179
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: BlockStems.h:78
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: BlockStems.h:25
virtual void BearFruit(cChunk &a_Chunk, const Vector3i a_StemRelPos) const override
Grows the final produce next to the stem at the specified position.
Definition: BlockStems.h:90
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: BlockStems.h:68
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: BlockStems.h:59
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
void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
Definition: Chunk.h:286
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
RealType RandReal(RealType a_Min, RealType a_Max)
Return a random RealType in the range [a_Min, a_Max).
Definition: FastRandom.h:123
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