Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockBigFlower.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "BlockHandler.h"
5 #include "ChunkInterface.h"
6 #include "../BlockInfo.h"
7 #include "../Items/ItemHandler.h"
8 
9 
10 
11 
13  public cBlockHandler
14 {
16 
17 public:
18 
19  using Super::Super;
20 
21 private:
22 
23  virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override
24  {
25  if (IsMetaTopPart(a_Meta))
26  {
27  BLOCKTYPE BottomType;
28  if (
29  (a_Position.y < 1) ||
30  !a_World.GetBlockTypeMeta(a_Position - Vector3i(0, 1, 0), BottomType, a_Meta) ||
31  (BottomType != E_BLOCK_BIG_FLOWER)
32  )
33  {
34  // Can't find the flower meta so assume grass
35  return true;
36  }
37  }
38 
39  NIBBLETYPE FlowerMeta = a_Meta & 0x07;
40  return (
41  (FlowerMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) ||
42  (FlowerMeta == E_META_BIG_FLOWER_LARGE_FERN)
43  );
44  }
45 
46 
47 
48 
49 
50  virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
51  {
52  if (IsMetaTopPart(a_BlockMeta))
53  {
54  return {};
55  }
56 
57  // With shears, drop self (even tall grass and fern):
58  if ((a_Tool != nullptr) && (a_Tool->m_ItemType == E_ITEM_SHEARS))
59  {
60  // Bit 0x08 specifies whether this is a top part or bottom; cut it off from the pickup:
61  return cItem(m_BlockType, 1, a_BlockMeta & 0x07);
62  }
63 
64  // Tall grass drops seeds, large fern drops nothing, others drop self:
65  auto flowerType = a_BlockMeta & 0x07;
66  if (flowerType == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS)
67  {
68 
69  // Drop seeds, depending on bernoulli trial result:
70  if (GetRandomProvider().RandBool(0.875))
71  {
72  // 87.5% chance of dropping nothing:
73  return {};
74  }
75 
76  // 12.5% chance of dropping some seeds.
77  const auto DropNum = FortuneDiscreteRandom(1, 1, 2 * ToolFortuneLevel(a_Tool));
78  return cItem(E_ITEM_SEEDS, DropNum);
79  }
80  else if (flowerType != E_META_BIG_FLOWER_LARGE_FERN)
81  {
82  return cItem(m_BlockType, 1, static_cast<short>(flowerType));
83  }
84 
85  return {};
86  }
87 
88 
89 
90 
91 
92  static bool IsMetaTopPart(NIBBLETYPE a_Meta)
93  {
94  return ((a_Meta & 0x08) != 0);
95  }
96 
97 
98 
99 
100 
101  virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
102  {
103  // CanBeAt is also called on placement, so the top part can't check for the bottom part.
104  // Both parts can only that they're rooted in grass.
105 
106  const auto RootPosition = a_Position.addedY(IsMetaTopPart(a_Meta) ? -2 : -1);
107  return (RootPosition.y >= 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition));
108  }
109 
110 
111 
112 
113 
114  virtual void OnBroken(
115  cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
116  const Vector3i a_BlockPos,
117  BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
118  const cEntity * a_Digger
119  ) const override
120  {
121  if (IsMetaTopPart(a_OldBlockMeta))
122  {
123  const auto LowerPart = a_BlockPos.addedY(-1);
124  if (a_ChunkInterface.GetBlock(LowerPart) == a_OldBlockType)
125  {
126  // Prevent creative punches from dropping pickups.
127  // TODO: Simplify to SetBlock and remove the IsMetaTopPart check in DropBlockAsPickups when 1.13 blockstates arrive.
128  if ((a_Digger != nullptr) && a_Digger->IsPlayer() && static_cast<const cPlayer *>(a_Digger)->IsGameModeCreative())
129  {
130  a_ChunkInterface.SetBlock(LowerPart, E_BLOCK_AIR, 0);
131  }
132  else
133  {
134  a_ChunkInterface.DropBlockAsPickups(LowerPart);
135  }
136  }
137  }
138  else
139  {
140  const auto UpperPart = a_BlockPos.addedY(1);
141  if (a_ChunkInterface.GetBlock(UpperPart) == a_OldBlockType)
142  {
143  a_ChunkInterface.SetBlock(UpperPart, E_BLOCK_AIR, 0);
144  }
145  }
146  }
147 
148 
149 
150 
151 
152  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
153  {
154  UNUSED(a_Meta);
155  return 7;
156  }
157 } ;
bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:86
@ E_META_BIG_FLOWER_DOUBLE_TALL_GRASS
Definition: BlockType.h:557
@ E_META_BIG_FLOWER_LARGE_FERN
Definition: BlockType.h:558
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_BIG_FLOWER
Definition: BlockType.h:194
@ E_ITEM_SEEDS
Definition: BlockType.h:339
@ 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
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
Byte ColourID
Definition: Globals.h:162
#define UNUSED
Definition: Globals.h:72
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...
static bool IsMetaTopPart(NIBBLETYPE a_Meta)
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.
virtual void OnBroken(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity *a_Digger) const override
Called after a block gets broken (replaced with air), by natural means.
virtual bool DoesIgnoreBuildCollision(const cWorld &a_World, const cItem &a_HeldItem, const Vector3i a_Position, NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override
Checks if the player can build "inside" this block.
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.
static unsigned char ToolFortuneLevel(const cItem *a_Tool)
Returns the fortune level of a tool, if it is a valid tool.
static char FortuneDiscreteRandom(char a_MinDrop, char a_DefaultMax, unsigned char a_BonusMax, char a_DropCap=25)
Returns a random number of drops taking into account fortune.
constexpr cBlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockHandler.h:29
const BLOCKTYPE m_BlockType
Definition: BlockHandler.h:205
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
BLOCKTYPE GetBlock(Vector3i a_Pos)
void DropBlockAsPickups(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Digs the block and spawns the relevant pickups, as if a_Digger used a_Tool to dig the block.
Definition: Chunk.h:36
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:146
Definition: Entity.h:76
bool IsPlayer(void) const
Definition: Entity.h:160
Definition: Player.h:29
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1025
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
T y
Definition: Vector3.h:17
Definition: World.h:53
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Retrieves the block type and meta at the specified coords.
Definition: World.cpp:1779