Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockFarmland.h
Go to the documentation of this file.
1 
2 // BlockFarmland.h
3 
4 // Declares the cBlcokFarmlandHandler representing the block handler for farmland
5 
6 
7 
8 
9 
10 #pragma once
11 
12 #include "BlockHandler.h"
13 #include "../BlockArea.h"
14 
15 
16 
17 
18 
20  public cClearMetaOnDrop<cBlockHandler>
21 {
23 
24 public:
25 
27  super(a_BlockType)
28  {
29  }
30 
31 
32 
33 
34 
35  virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
36  {
37  NIBBLETYPE BlockMeta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
38 
39  if (IsWaterInNear(a_Chunk, a_RelX, a_RelY, a_RelZ))
40  {
41  // Water was found, set block meta to 7
42  a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, 7);
43  return;
44  }
45 
46  // Water wasn't found, de-hydrate block:
47  if (BlockMeta > 0)
48  {
49  a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_FARMLAND, --BlockMeta);
50  return;
51  }
52 
53  // Farmland too dry. If nothing is growing on top, turn back to dirt:
54  BLOCKTYPE UpperBlock = (a_RelY >= cChunkDef::Height - 1) ? static_cast<BLOCKTYPE>(E_BLOCK_AIR) : a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
55  switch (UpperBlock)
56  {
57  case E_BLOCK_BEETROOTS:
58  case E_BLOCK_CROPS:
59  case E_BLOCK_POTATOES:
60  case E_BLOCK_CARROTS:
61  case E_BLOCK_MELON_STEM:
63  {
64  // Produce on top, don't revert
65  break;
66  }
67  default:
68  {
69  a_Chunk.SetBlock({a_RelX, a_RelY, a_RelZ}, E_BLOCK_DIRT, 0);
70  break;
71  }
72  }
73  }
74 
75 
76 
77 
78 
79  virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
80  {
81  // Don't care about any neighbor but the one above us (fix recursion loop in #2213):
82  if (a_WhichNeighbor != BLOCK_FACE_YP)
83  {
84  return;
85  }
86 
87  // Don't care about anything if we're at the top of the world:
88  if (a_BlockPos.y >= cChunkDef::Height)
89  {
90  return;
91  }
92 
93  // Check whether we should revert to dirt:
94  auto upperBlock = a_ChunkInterface.GetBlock(a_BlockPos.addedY(1));
95  if (cBlockInfo::FullyOccupiesVoxel(upperBlock))
96  {
97  a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_DIRT, 0);
98  }
99  }
100 
101 
102 
103 
104 
105  bool IsWaterInNear(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
106  {
107  if (a_Chunk.GetWorld()->IsWeatherWetAt(a_RelX, a_RelZ))
108  {
109  // Rain hydrates farmland, too, except in Desert biomes.
110  return true;
111  }
112 
113  // Search for water in a close proximity:
114  // Ref.: https://minecraft.gamepedia.com/Farmland#Hydration
115  // TODO: Rewrite this to use the chunk and its neighbors directly
116  cBlockArea Area;
117  int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
118  int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
119  if (!Area.Read(*a_Chunk.GetWorld(), BlockX - 4, BlockX + 4, a_RelY, a_RelY + 1, BlockZ - 4, BlockZ + 4))
120  {
121  // Too close to the world edge, cannot check surroundings
122  return false;
123  }
124 
125  size_t NumBlocks = Area.GetBlockCount();
126  BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
127  for (size_t i = 0; i < NumBlocks; i++)
128  {
129  if (IsBlockWater(BlockTypes[i]))
130  {
131  return true;
132  }
133  } // for i - BlockTypes[]
134 
135  return false;
136  }
137 
138  virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override
139  {
140  return (
141  (a_Plant == E_BLOCK_BEETROOTS) ||
142  (a_Plant == E_BLOCK_CROPS) ||
143  (a_Plant == E_BLOCK_CARROTS) ||
144  (a_Plant == E_BLOCK_POTATOES) ||
145  (a_Plant == E_BLOCK_MELON_STEM) ||
146  (a_Plant == E_BLOCK_PUMPKIN_STEM)
147  );
148  }
149 } ;
cWorld * GetWorld(void) const
Definition: Chunk.h:153
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: Defines.h:436
virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override
Checks whether the block has an effect on growing the plant.
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
static const int Width
Definition: ChunkDef.h:134
bool IsWaterInNear(cChunk &a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
virtual void OnUpdate(cChunkInterface &cChunkInterface, cWorldInterface &a_WorldInterface, cBlockPluginInterface &a_PluginInterface, cChunk &a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
Called when the block gets ticked either by a random tick or by a queued tick.
Definition: BlockFarmland.h:35
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: Chunk.cpp:1313
BLOCKTYPE m_BlockType
Definition: BlockHandler.h:213
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
Definition: Chunk.h:49
T y
Definition: Vector3.h:17
static const int Height
Definition: ChunkDef.h:135
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:299
This interface is used to decouple block handlers from the cPluginManager dependency through cWorld...
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:380
cBlockFarmlandHandler(BLOCKTYPE a_BlockType)
Definition: BlockFarmland.h:26
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override
Returns true if it is raining or storming at the specified location.
Definition: World.h:1025
int GetPosX(void) const
Definition: Chunk.h:150
size_t GetBlockCount(void) const
Definition: BlockArea.h:390
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
BLOCKTYPE GetBlock(Vector3i a_Pos)
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:177
bool Read(cForEachChunkProvider &a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes=baTypes|baMetas|baBlockEntities)
Reads an area of blocks specified.
Definition: BlockArea.cpp:443
int GetPosZ(void) const
Definition: Chunk.h:151
virtual void OnNeighborChanged(cChunkInterface &a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
Called when a direct neighbor of this block has been changed.
Definition: BlockFarmland.h:79
BLOCKTYPE * GetBlockTypes(void) const
Returns the internal pointer to the block types.
Definition: BlockArea.h:386
Mixin to clear the block&#39;s meta value when converting to a pickup.
Definition: Mixins.h:55
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients=true)
Definition: Chunk.cpp:1402