summaryrefslogtreecommitdiffstats
path: root/src/Items/ItemBanner.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Items/ItemBanner.h')
-rw-r--r--src/Items/ItemBanner.h215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/Items/ItemBanner.h b/src/Items/ItemBanner.h
new file mode 100644
index 000000000..7b9e6d05b
--- /dev/null
+++ b/src/Items/ItemBanner.h
@@ -0,0 +1,215 @@
+
+
+#pragma once
+
+#include "ItemHandler.h"
+#include "../World.h"
+#include "../Blocks/BlockHandler.h"
+#include "../BlockEntities/BannerEntity.h"
+#include "../Blocks/ChunkInterface.h"
+
+
+
+
+
+class cItemBannerHandler:
+ public cItemHandler
+{
+ using Super = cItemHandler;
+
+public:
+
+ cItemBannerHandler(int a_ItemType):
+ Super(a_ItemType)
+ {
+ }
+
+
+
+
+
+ virtual bool IsPlaceable(void) override
+ {
+ return true;
+ }
+
+
+
+
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ const Vector3i a_PlacedBlockPos,
+ eBlockFace a_ClickedBlockFace,
+ const Vector3i a_CursorPos,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockMeta = 0x00;
+ const double Rotation = a_Player->GetYaw();
+
+ // Placing on the floor
+ if (a_ClickedBlockFace == BLOCK_FACE_TOP)
+ {
+ if ((Rotation >= - 11.25f) && (Rotation < 11.25f))
+ {
+ // South
+ a_BlockMeta |= 0x08;
+ }
+ else if ((Rotation >= 11.25f) && (Rotation < 33.75f))
+ {
+ // SouthSouthWest
+ a_BlockMeta |= 0x09;
+ }
+ else if ((Rotation >= 23.75f) && (Rotation < 56.25f))
+ {
+ // SouthWest
+ a_BlockMeta |= 0x0a;
+ }
+ else if ((Rotation >= 56.25f) && (Rotation < 78.75f))
+ {
+ // WestSouthWest
+ a_BlockMeta |= 0x0b;
+ }
+ else if ((Rotation >= 78.75f) && (Rotation < 101.25f))
+ {
+ // West
+ a_BlockMeta |= 0x0c;
+ }
+ else if ((Rotation >= 101.25f) && (Rotation < 123.75f))
+ {
+ // WestNorthWest
+ a_BlockMeta |= 0x0d;
+ }
+ else if ((Rotation >= 123.75f) && (Rotation < 146.25f))
+ {
+ // NorthWest
+ a_BlockMeta |= 0x0e;
+ }
+ else if ((Rotation >= 146.25f) && (Rotation < 168.75f))
+ {
+ // NorthNorthWest
+ a_BlockMeta |= 0x0f;
+ }
+ else if ((Rotation >= -168.75f) && (Rotation < -146.25f))
+ {
+ // NorthNorthEast
+ a_BlockMeta |= 0x01;
+ }
+ else if ((Rotation >= -146.25f) && (Rotation < -123.75f))
+ {
+ // NorthEast
+ a_BlockMeta |= 0x02;
+ }
+ else if ((Rotation >= -123.75f) && (Rotation < -101.25f))
+ {
+ // EastNorthEast
+ a_BlockMeta |= 0x03;
+ }
+ else if ((Rotation >= -101.25) && (Rotation < -78.75f))
+ {
+ // East
+ a_BlockMeta |= 0x04;
+ }
+ else if ((Rotation >= -78.75) && (Rotation < -56.25f))
+ {
+ // EastSouthEast
+ a_BlockMeta |= 0x05;
+ }
+ else if ((Rotation >= -56.25f) && (Rotation < -33.75f))
+ {
+ // SouthEast
+ a_BlockMeta |= 0x06;
+ }
+ else if ((Rotation >= -33.75f) && (Rotation < -11.25f))
+ {
+ // SouthSouthEast
+ a_BlockMeta |= 0x07;
+ }
+ else // degrees jumping from 180 to -180
+ {
+ // North
+ a_BlockMeta |= 0x00;
+ }
+ a_BlockType = E_BLOCK_STANDING_BANNER;
+ }
+ // placing on the sides
+ else if (a_ClickedBlockFace != BLOCK_FACE_NONE)
+ {
+ if (a_ClickedBlockFace == BLOCK_FACE_EAST)
+ {
+ a_BlockMeta |= 0x05;
+ }
+ else if (a_ClickedBlockFace == BLOCK_FACE_WEST)
+ {
+ a_BlockMeta |= 0x04;
+ }
+ else if (a_ClickedBlockFace == BLOCK_FACE_NORTH)
+ {
+ a_BlockMeta |= 0x02;
+ }
+ else // degrees jumping from 180 to -180
+ {
+ a_BlockMeta |= 0x03;
+ }
+ a_BlockType = E_BLOCK_WALL_BANNER;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+
+
+ virtual bool OnPlayerPlace(
+ cWorld & a_World,
+ cPlayer & a_Player,
+ const cItem & a_EquippedItem,
+ const Vector3i a_ClickedBlockPos,
+ eBlockFace a_ClickedBlockFace,
+ const Vector3i a_CursorPos
+ ) override
+ {
+ // Cannot place a banner at "no face" and from the bottom:
+ if ((a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockFace == BLOCK_FACE_BOTTOM))
+ {
+ return true;
+ }
+
+ // Checks if the banner replaced the block
+ BLOCKTYPE ClickedBlockType;
+ NIBBLETYPE ClickedBlockMeta;
+ a_World.GetBlockTypeMeta(a_ClickedBlockPos, ClickedBlockType, ClickedBlockMeta);
+ cChunkInterface ChunkInterface(a_World.GetChunkMap());
+ bool IsReplacingClickedBlock = cBlockHandler::For(ClickedBlockType).DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta);
+ if (IsReplacingClickedBlock)
+ {
+ // TODO: There is a bug in the network which prevents the client from receiving the new block entity on placement
+ // For now the replaced blocks are disabled
+ return false;
+ }
+
+ // saving the color of the banner in case it's the players last one
+ NIBBLETYPE Color = static_cast<NIBBLETYPE>(a_EquippedItem.m_ItemDamage);
+
+ if (!Super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_ClickedBlockPos, a_ClickedBlockFace, a_ClickedBlockPos))
+ {
+ return false;
+ }
+
+ const auto BannerPos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
+ return a_World.DoWithBlockEntityAt(BannerPos.x, BannerPos.y, BannerPos.z, [Color](cBlockEntity & a_BlockEntity)
+ {
+ ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_STANDING_BANNER) || (a_BlockEntity.GetBlockType() == E_BLOCK_WALL_BANNER));
+
+ auto & Banner = static_cast<cBannerEntity &>(a_BlockEntity);
+ Banner.SetBaseColor(Color);
+ return true;
+ });
+ }
+};