summaryrefslogtreecommitdiffstats
path: root/src/Blocks/BlockBigFlower.h
blob: c21e411f3dc9ce4db11513cd091654f7519aa0ec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

#pragma once

#include "BlockHandler.h"
#include "ChunkInterface.h"
#include "../BlockInfo.h"
#include "../Items/ItemHandler.h"




class cBlockBigFlowerHandler final :
	public cBlockHandler
{
	using Super = cBlockHandler;

public:

	using Super::Super;

private:

	virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) const override
	{
		if (IsMetaTopPart(a_Meta))
		{
			BLOCKTYPE BottomType;
			if (
				(a_Pos.y < 1) ||
				!a_ChunkInterface.GetBlockTypeMeta(a_Pos - Vector3i(0, 1, 0), BottomType, a_Meta) ||
				(BottomType != E_BLOCK_BIG_FLOWER)
			)
			{
				// Can't find the flower meta so assume grass
				return true;
			}
		}

		NIBBLETYPE FlowerMeta = a_Meta & 0x07;
		return (
			(FlowerMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) ||
			(FlowerMeta == E_META_BIG_FLOWER_LARGE_FERN)
		);
	}





	virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
	{
		if (IsMetaTopPart(a_BlockMeta))
		{
			return {};  // No drops from the top part
		}

		// With shears, drop self (even tall grass and fern):
		if ((a_Tool != nullptr) && (a_Tool->m_ItemType == E_ITEM_SHEARS))
		{
			// Bit 0x08 specifies whether this is a top part or bottom; cut it off from the pickup:
			return cItem(m_BlockType, 1, a_BlockMeta & 0x07);
		}

		// Tall grass drops seeds, large fern drops nothing, others drop self:
		auto flowerType = a_BlockMeta & 0x07;
		if (flowerType == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS)
		{

			// Drop seeds, depending on bernoulli trial result:
			if (GetRandomProvider().RandBool(0.875))
			{
				// 87.5% chance of dropping nothing:
				return {};
			}

			// 12.5% chance of dropping some seeds.
			const auto DropNum = FortuneDiscreteRandom(1, 1, 2 * ToolFortuneLevel(a_Tool));
			return cItem(E_ITEM_SEEDS, DropNum);
		}
		else if (flowerType != E_META_BIG_FLOWER_LARGE_FERN)
		{
			return cItem(m_BlockType, 1, static_cast<short>(flowerType));
		}

		return {};
	}





	static bool IsMetaTopPart(NIBBLETYPE a_Meta)
	{
		return ((a_Meta & 0x08) != 0);
	}





	virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override
	{
		if (a_RelPos.y <= 0)
		{
			return false;
		}
		BLOCKTYPE BlockType;
		NIBBLETYPE BlockMeta;
		a_Chunk.GetBlockTypeMeta(a_RelPos.addedY(-1), BlockType, BlockMeta);

		return IsBlockTypeOfDirt(BlockType) || ((BlockType == E_BLOCK_BIG_FLOWER) && !IsMetaTopPart(BlockMeta));
	}





	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
	{
		UNUSED(a_Digger);
		if ((a_OldBlockMeta & 0x8) != 0)
		{
			// Was upper part of flower
			auto lowerPartPos = a_BlockPos - Vector3i(0, 1, 0);
			if (a_ChunkInterface.GetBlock(lowerPartPos) == a_OldBlockType)
			{
				a_ChunkInterface.DropBlockAsPickups(lowerPartPos);
			}
		}
		else
		{
			// Was lower part
			auto upperPartPos = a_BlockPos + Vector3i(0, 1, 0);
			if (a_ChunkInterface.GetBlock(upperPartPos) == a_OldBlockType)
			{
				a_ChunkInterface.DropBlockAsPickups(upperPartPos);
			}
		}
	}





	virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
	{
		UNUSED(a_Meta);
		return 7;
	}
} ;