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_ID StemPickupType>
15  public cBlockPlant<true>
16 {
18 
19 public:
20 
22  super(a_BlockType)
23  {
24  }
25 
26 
27 
28 
29 
30  virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override
31  {
32  return cItem(StemPickupType, 1, 0);
33  }
34 
35 
36 
37 
38 
39  virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
40  {
41  return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
42  }
43 
44 
45 
46 
47 
48  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
49  {
50  UNUSED(a_Meta);
51  return 7;
52  }
53 
54 
55 
56 
57 
58  virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) override
59  {
60  auto oldMeta = a_Chunk.GetMeta(a_RelPos);
61  auto meta = oldMeta + a_NumStages;
62  a_Chunk.SetBlock(a_RelPos, m_BlockType, static_cast<NIBBLETYPE>(std::min(meta, 7))); // Update the stem
63  if (meta > 7)
64  {
65  if (growProduce(a_Chunk, a_RelPos))
66  {
67  return 8 - oldMeta;
68  }
69  else
70  {
71  return 7 - oldMeta;
72  }
73  }
74  return meta - oldMeta;
75  }
76 
77 
78 
79 
80 protected:
81 
84  bool growProduce(cChunk & a_Chunk, Vector3i a_StemRelPos)
85  {
86  auto & random = GetRandomProvider();
87 
88  // Check if there's another produce around the stem, if so, abort:
89  static const Vector3i neighborOfs[] =
90  {
91  { 1, 0, 0},
92  {-1, 0, 0},
93  { 0, 0, 1},
94  { 0, 0, -1},
95  };
96  bool isValid;
97  BLOCKTYPE blockType[4];
98  NIBBLETYPE blockMeta; // unused
99  isValid = a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[0], blockType[0], blockMeta);
100  isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[1], blockType[1], blockMeta);
101  isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[2], blockType[2], blockMeta);
102  isValid = isValid && a_Chunk.UnboundedRelGetBlock(a_StemRelPos + neighborOfs[3], blockType[3], blockMeta);
103  if (
104  !isValid ||
105  (blockType[0] == ProduceBlockType) ||
106  (blockType[1] == ProduceBlockType) ||
107  (blockType[2] == ProduceBlockType) ||
108  (blockType[3] == ProduceBlockType)
109  )
110  {
111  // Neighbors not valid or already taken by the same produce
112  return false;
113  }
114 
115  // Pick a direction in which to place the produce:
116  int x = 0, z = 0;
117  int checkType = random.RandInt(3); // The index to the neighbors array which should be checked for emptiness
118  switch (checkType)
119  {
120  case 0: x = 1; break;
121  case 1: x = -1; break;
122  case 2: z = 1; break;
123  case 3: z = -1; break;
124  }
125 
126  // Check that the block in that direction is empty:
127  switch (blockType[checkType])
128  {
129  case E_BLOCK_AIR:
130  case E_BLOCK_SNOW:
131  case E_BLOCK_TALL_GRASS:
132  case E_BLOCK_DEAD_BUSH:
133  {
134  break;
135  }
136  default: return false;
137  }
138 
139  // Check if there's soil under the neighbor. We already know the neighbors are valid. Place produce if ok
140  BLOCKTYPE soilType;
141  auto produceRelPos = a_StemRelPos + Vector3i(x, 0, z);
142  VERIFY(a_Chunk.UnboundedRelGetBlock(produceRelPos.addedY(-1), soilType, blockMeta));
143  switch (soilType)
144  {
145  case E_BLOCK_DIRT:
146  case E_BLOCK_GRASS:
147  case E_BLOCK_FARMLAND:
148  {
149  // Place a randomly-facing produce:
150  NIBBLETYPE meta = (ProduceBlockType == E_BLOCK_MELON) ? 0 : static_cast<NIBBLETYPE>(random.RandInt(4) % 4);
151  auto produceAbsPos = a_Chunk.RelativeToAbsolute(produceRelPos);
152  FLOGD("Growing melon / pumpkin at {0} (<{1}, {2}> from stem), overwriting {3}, growing on top of {4}, meta {5}",
153  produceAbsPos,
154  x, z,
155  ItemTypeToString(blockType[checkType]),
156  ItemTypeToString(soilType),
157  meta
158  );
159  a_Chunk.GetWorld()->SetBlock(produceAbsPos, ProduceBlockType, meta);
160  return true;
161  }
162  }
163  return false;
164  }
165 } ;
166 
169 
170 
171 
cWorld * GetWorld(void) const
Definition: Chunk.h:153
#define VERIFY(x)
Definition: Globals.h:339
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity *a_BlockEntity, const cEntity *a_Digger, const cItem *a_Tool) override
Returns the pickups that would result if the block was mined by a_Digger using a_Tool.
Definition: BlockStems.h:30
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
Vector3i RelativeToAbsolute(Vector3i a_RelBlockPosition)
Converts the coord relative to this chunk into an absolute coord.
Definition: Chunk.h:569
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: Chunk.cpp:1313
BLOCKTYPE m_BlockType
Definition: BlockHandler.h:213
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: BlockStems.h:39
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
Definition: Chunk.h:49
virtual int Grow(cChunk &a_Chunk, Vector3i a_RelPos, int a_NumStages=1) override
Grows this block, if it supports growing, by the specified amount of stages (at most).
Definition: BlockStems.h:58
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:380
cBlockStemsHandler(BLOCKTYPE a_BlockType)
Definition: BlockStems.h:21
Handler for stems from which produce grows in an adjacent block (melon, pumpkin) after it becomes rip...
Definition: BlockStems.h:14
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: BlockStems.h:48
bool growProduce(cChunk &a_Chunk, Vector3i a_StemRelPos)
Grows the final produce next to the stem at the specified pos.
Definition: BlockStems.h:84
#define UNUSED
Definition: Globals.h:152
#define FLOGD(...)
Definition: LoggerSimple.h:48
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
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:177
Byte ColourID
Definition: Globals.h:118
Base class for plants that use light values to decide whether to grow or not.
Definition: BlockPlant.h:12
Definition: Entity.h:73
Vector3< int > Vector3i
Definition: Vector3.h:447
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
Definition: World.cpp:1873
Definition: Item.h:36
AString ItemTypeToString(short a_ItemType)
Translates itemtype into a string.
Definition: BlockID.cpp:270
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:234