summaryrefslogtreecommitdiffstats
path: root/src/Blocks/BlockStairs.h
blob: 3d7dd1442c2b7f8efce5139b8ee28ce97ba72bd6 (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

#pragma once

#include "BlockHandler.h"
#include "MetaRotator.h"




class cBlockStairsHandler :
	public cMetaRotator<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>
{
public:
	cBlockStairsHandler(BLOCKTYPE a_BlockType) :
		cMetaRotator<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>(a_BlockType)
	{

	}

	virtual bool GetPlacementBlockTypeMeta(
		cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
		int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
		int a_CursorX, int a_CursorY, int a_CursorZ,
		BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
	) override
	{
		UNUSED(a_ChunkInterface);
		UNUSED(a_BlockX);
		UNUSED(a_BlockY);
		UNUSED(a_BlockZ);
		UNUSED(a_CursorX);
		UNUSED(a_CursorZ);
		a_BlockType = m_BlockType;
		a_BlockMeta = RotationToMetaData(a_Player->GetYaw());
		switch (a_BlockFace)
		{
			case BLOCK_FACE_TOP:    break;
			case BLOCK_FACE_BOTTOM: a_BlockMeta = a_BlockMeta | 0x4; break;  // When placing onto a bottom face, always place an upside-down stairs block
			case BLOCK_FACE_EAST:
			case BLOCK_FACE_NORTH:
			case BLOCK_FACE_SOUTH:
			case BLOCK_FACE_WEST:
			{
				// When placing onto a sideways face, check cursor, if in top half, make it an upside-down stairs block
				if (a_CursorY > 8)
				{
					a_BlockMeta |= 0x4;
				}
				break;
			}
			case BLOCK_FACE_NONE: return false;
		}
		return true;
	}

	virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
	{
		// Reset meta to zero
		a_Pickups.push_back(cItem(m_BlockType, 1, 0));
	}

	static NIBBLETYPE RotationToMetaData(double a_Rotation)
	{
		a_Rotation += 90 + 45;  // So its not aligned with axis
		if (a_Rotation > 360)
		{
			a_Rotation -= 360;
		}
		if ((a_Rotation >= 0) && (a_Rotation < 90))
		{
			return 0x0;
		}
		else if ((a_Rotation >= 180) && (a_Rotation < 270))
		{
			return 0x1;
		}
		else if ((a_Rotation >= 90) && (a_Rotation < 180))
		{
			return 0x2;
		}
		else
		{
			return 0x3;
		}
	}

	virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
	{
		// Toggle bit 3:
		return (a_Meta & 0x0b) | ((~a_Meta) & 0x04);
	}

	virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
	{
		UNUSED(a_Meta);
		switch (m_BlockType)
		{
			case E_BLOCK_SANDSTONE_STAIRS:
			case E_BLOCK_BIRCH_WOOD_STAIRS: return 2;
			case E_BLOCK_QUARTZ_STAIRS: return 8;
			case E_BLOCK_JUNGLE_WOOD_STAIRS:
			case E_BLOCK_RED_SANDSTONE_STAIRS: return 10;
			case E_BLOCK_COBBLESTONE_STAIRS:
			case E_BLOCK_STONE_BRICK_STAIRS: return 11;
			case E_BLOCK_OAK_WOOD_STAIRS: return 13;
			case E_BLOCK_ACACIA_WOOD_STAIRS: return 15;
			case E_BLOCK_DARK_OAK_WOOD_STAIRS: return 26;
			case E_BLOCK_BRICK_STAIRS: return 28;
			case E_BLOCK_NETHER_BRICK_STAIRS: return 35;
			case E_BLOCK_SPRUCE_WOOD_STAIRS: return 34;
			default:
			{
				ASSERT(!"Unhandled blocktype in stairs handler!");
				return 0;
			}
		}
	}

	/** EXCEPTION a.k.a. why is this removed:
	This collision-detection is actually more accurate than the client, but since the client itself
	sends inaccurate / sparse data, it's easier to just err on the side of the client and keep the
	two in sync by assuming that if a player hit ANY of the stair's bounding cube, it counts as the ground. */
	#if 0
	bool IsInsideBlock(const Vector3d & a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta)
	{
		if (a_BlockMeta & 0x4)  // upside down
		{
			return true;
		}
		else if ((a_BlockMeta & 0x3) == 0)  // tall side is east (+X)
		{
			return a_Position.y < ((a_Position.x > 0.5) ? 1.0 : 0.5);
		}
		else if ((a_BlockMeta & 0x3) == 1)  // tall side is west (-X)
		{
			return a_Position.y < ((a_Position.x < 0.5) ? 1.0 : 0.5);
		}
		else if ((a_BlockMeta & 0x3) == 2)  // tall side is south (+Z)
		{
			return a_Position.y < ((a_Position.z > 0.5) ? 1.0 : 0.5);
		}
		else if ((a_BlockMeta & 0x3) == 3)  // tall side is north (-Z)
		{
			return a_Position.y < ((a_Position.z < 0.5) ? 1.0 : 0.5);
		}
		return false;
	}
	#endif

} ;