summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/BlockEntities/BannerEntity.cpp78
-rw-r--r--src/BlockEntities/BannerEntity.h43
-rw-r--r--src/BlockEntities/BlockEntity.cpp8
-rw-r--r--src/BlockEntities/CMakeLists.txt2
-rw-r--r--src/Blocks/BlockBanner.h51
-rw-r--r--src/Blocks/BlockHandler.cpp5
-rw-r--r--src/Blocks/CMakeLists.txt1
-rw-r--r--src/Defines.h48
-rw-r--r--src/Items/CMakeLists.txt1
-rw-r--r--src/Items/ItemBanner.h215
-rw-r--r--src/Items/ItemHandler.cpp2
-rw-r--r--src/Protocol/Protocol_1_10.cpp13
-rw-r--r--src/Protocol/Protocol_1_11.cpp13
-rw-r--r--src/Protocol/Protocol_1_8.cpp28
-rw-r--r--src/Protocol/Protocol_1_9.cpp13
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp19
-rw-r--r--src/WorldStorage/NamespaceSerializer.cpp54
-rw-r--r--src/WorldStorage/NamespaceSerializer.h6
-rw-r--r--src/WorldStorage/WSSAnvil.cpp31
-rw-r--r--[-rwxr-xr-x]src/WorldStorage/WSSAnvil.h1
20 files changed, 617 insertions, 15 deletions
diff --git a/src/BlockEntities/BannerEntity.cpp b/src/BlockEntities/BannerEntity.cpp
new file mode 100644
index 000000000..d7fda3cf7
--- /dev/null
+++ b/src/BlockEntities/BannerEntity.cpp
@@ -0,0 +1,78 @@
+
+// BannerEntity.cpp
+
+// Implements the cBannerEntity class representing a banner block in the world
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+#include "BannerEntity.h"
+
+#include "../World.h"
+#include "../ClientHandle.h"
+
+
+
+
+
+cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) :
+ cBannerEntity(a_BlockType, a_BlockMeta, a_Pos, a_World, 1)
+{
+}
+
+
+
+
+
+cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor):
+ Super(a_BlockType, a_BlockMeta, a_Pos, a_World),
+ m_BaseColor(a_BaseColor)
+{
+ ASSERT((a_BlockType == E_BLOCK_WALL_BANNER) || (a_BlockType == E_BLOCK_STANDING_BANNER));
+}
+
+
+
+
+
+void cBannerEntity::CopyFrom(const cBlockEntity & a_Src)
+{
+ Super::CopyFrom(a_Src);
+ auto & src = static_cast<const cBannerEntity &>(a_Src);
+ m_BaseColor = src.m_BaseColor;
+}
+
+
+
+
+
+void cBannerEntity::SendTo(cClientHandle & a_Client)
+{
+ a_Client.SendBlockChange(m_Pos.x, m_Pos.y, m_Pos.z, m_BlockType, m_BlockMeta);
+ a_Client.SendUpdateBlockEntity(*this);
+}
+
+
+
+
+
+cItems cBannerEntity::ConvertToPickups() const
+{
+ return cItem(E_ITEM_BANNER, 1, static_cast<NIBBLETYPE>(GetBaseColor()));
+}
+
+
+
+
+
+unsigned char cBannerEntity::GetBaseColor() const
+{
+ return m_BaseColor;
+}
+
+
+
+
+
+void cBannerEntity::SetBaseColor(const unsigned char a_Color)
+{
+ m_BaseColor = a_Color;
+}
diff --git a/src/BlockEntities/BannerEntity.h b/src/BlockEntities/BannerEntity.h
new file mode 100644
index 000000000..d265f3279
--- /dev/null
+++ b/src/BlockEntities/BannerEntity.h
@@ -0,0 +1,43 @@
+
+// BannerEntity.h
+
+// Declares the cBannerEntity class representing a single banner in the world
+
+
+
+
+
+#pragma once
+
+#include "BlockEntity.h"
+
+
+
+
+
+// tolua_begin
+class cBannerEntity :
+ public cBlockEntity
+{
+ // tolua_end
+
+ using Super = cBlockEntity;
+
+public:
+
+ cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
+ cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor);
+
+ unsigned char GetBaseColor() const;
+ void SetBaseColor(unsigned char a_Color);
+
+private:
+
+ unsigned char m_BaseColor;
+
+ // cBlockEntity overrides:
+ virtual cItems ConvertToPickups() const override;
+ virtual void CopyFrom(const cBlockEntity & a_Src) override;
+ virtual void SendTo(cClientHandle & a_Client) override;
+ virtual bool UsedBy(cPlayer * a_Player) override { return true; }
+} ; // tolua_export
diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp
index a3b6b33a3..4b17f10a6 100644
--- a/src/BlockEntities/BlockEntity.cpp
+++ b/src/BlockEntities/BlockEntity.cpp
@@ -4,6 +4,7 @@
// Implements the cBlockEntity class that is the common ancestor for all block entities
#include "Globals.h"
+#include "BannerEntity.h"
#include "BeaconEntity.h"
#include "BedEntity.h"
#include "BlockEntity.h"
@@ -77,6 +78,11 @@ OwnedBlockEntity cBlockEntity::CreateByBlockType(const BLOCKTYPE a_BlockType, co
{
switch (a_BlockType)
{
+ // Banners:
+ case E_BLOCK_STANDING_BANNER:
+ case E_BLOCK_WALL_BANNER: return std::make_unique<cBannerEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
+
+ // Others:
case E_BLOCK_BEACON: return std::make_unique<cBeaconEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_BED: return std::make_unique<cBedEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_BREWING_STAND: return std::make_unique<cBrewingstandEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
@@ -144,7 +150,9 @@ bool cBlockEntity::IsBlockEntityBlockType(const BLOCKTYPE a_BlockType)
case E_BLOCK_MOB_SPAWNER:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_SIGN_POST:
+ case E_BLOCK_STANDING_BANNER:
case E_BLOCK_TRAPPED_CHEST:
+ case E_BLOCK_WALL_BANNER:
case E_BLOCK_WALLSIGN:
{
return true;
diff --git a/src/BlockEntities/CMakeLists.txt b/src/BlockEntities/CMakeLists.txt
index d8ec1e005..63583d185 100644
--- a/src/BlockEntities/CMakeLists.txt
+++ b/src/BlockEntities/CMakeLists.txt
@@ -1,6 +1,7 @@
target_sources(
${CMAKE_PROJECT_NAME} PRIVATE
+ BannerEntity.cpp
BeaconEntity.cpp
BedEntity.cpp
BlockEntity.cpp
@@ -23,6 +24,7 @@ target_sources(
NoteEntity.cpp
SignEntity.cpp
+ BannerEntity.h
BeaconEntity.h
BedEntity.h
BlockEntity.h
diff --git a/src/Blocks/BlockBanner.h b/src/Blocks/BlockBanner.h
new file mode 100644
index 000000000..2a6e62aba
--- /dev/null
+++ b/src/Blocks/BlockBanner.h
@@ -0,0 +1,51 @@
+
+// BlockBanner.h
+
+#pragma once
+
+#include "../BlockInfo.h"
+#include "BlockEntity.h"
+
+
+
+
+
+class cBlockBannerHandler final :
+ public cBlockEntityHandler
+{
+ using Super = cBlockEntityHandler;
+
+public:
+
+ using Super::Super;
+
+ virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cEntity * a_Digger, const cItem * a_Tool) const override
+ {
+ // Drops handled by the block entity:
+ return {};
+ }
+
+
+
+
+
+ virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override
+ {
+ if (a_RelPos.y < 1)
+ {
+ return false;
+ }
+
+ return cBlockInfo::IsSolid(a_Chunk.GetBlock(a_RelPos.addedY(-1)));
+ }
+
+
+
+
+
+ virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
+ {
+ UNUSED(a_Meta);
+ return 0;
+ }
+} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index dec1eddf9..d2fbf4e1a 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -7,6 +7,7 @@
#include "BlockPluginInterface.h"
#include "BlockAir.h"
#include "BlockAnvil.h"
+#include "BlockBanner.h"
#include "BlockBed.h"
#include "BlockBigFlower.h"
#include "BlockBookShelf.h"
@@ -412,7 +413,7 @@ namespace
constexpr cDefaultBlockHandler BlockStainedClayHandler (E_BLOCK_STAINED_CLAY);
constexpr cBlockGlassHandler BlockStainedGlassHandler (E_BLOCK_STAINED_GLASS);
constexpr cBlockGlassHandler BlockStainedGlassPaneHandler (E_BLOCK_STAINED_GLASS_PANE);
- constexpr cDefaultBlockHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER); // TODO: drops correct?
+ constexpr cBlockBannerHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER);
constexpr cBlockLavaHandler BlockStationaryLavaHandler (E_BLOCK_STATIONARY_LAVA);
constexpr cBlockWaterHandler BlockStationaryWaterHandler (E_BLOCK_STATIONARY_WATER);
constexpr cBlockPistonHandler BlockStickyPistonHandler (E_BLOCK_STICKY_PISTON);
@@ -433,7 +434,7 @@ namespace
constexpr cBlockTripwireHandler BlockTripwireHandler (E_BLOCK_TRIPWIRE);
constexpr cBlockTripwireHookHandler BlockTripwireHookHandler (E_BLOCK_TRIPWIRE_HOOK);
constexpr cBlockVineHandler BlockVinesHandler (E_BLOCK_VINES);
- constexpr cDefaultBlockHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER); // TODO: drops correct?
+ constexpr cBlockBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER);
constexpr cBlockWallSignHandler BlockWallsignHandler (E_BLOCK_WALLSIGN);
constexpr cBlockWaterHandler BlockWaterHandler (E_BLOCK_WATER);
constexpr cBlockGlazedTerracottaHandler BlockWhiteGlazedTerracottaHandler (E_BLOCK_WHITE_GLAZED_TERRACOTTA);
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index 770b0dab8..f69350c30 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -9,6 +9,7 @@ target_sources(
BlockAir.h
BlockAnvil.h
+ BlockBanner.h
BlockBed.h
BlockBigFlower.h
BlockBookShelf.h
diff --git a/src/Defines.h b/src/Defines.h
index cf030bdd7..417f28a42 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -395,6 +395,54 @@ enum eMessageType
+enum class BannerPattern
+{
+ BottomStripe,
+ TopStripe,
+ LeftStripe,
+ RightStripe,
+ CenterStripeVertical,
+ MiddleStripeHorizontal,
+ DownRightStripe,
+ DownLeftStripe,
+ SmallVerticalStripes,
+ DiagonalCross,
+ SquareCross,
+ LeftOfDiagonal,
+ RightOfUpsideDownDiagonal,
+ LeftOfUpsideDownDiagonal,
+ RightOfDiagonal,
+ VerticalHalfLeft,
+ VerticalHalfRight,
+ HorizontalHalfTop,
+ HorizontalHalfBottom,
+ BottomLeftCorner,
+ BottomRightCorner,
+ TopLeftCorner,
+ TopRightCorner,
+ BottomTriangle,
+ TopTriangle,
+ BottomTriangleSawtooth,
+ TopTriangleSawtooth,
+ MiddleCircle,
+ MiddleRhombus,
+ Border,
+ CurlyBorder,
+ Brick,
+ Gradient,
+ GradientUpsideDown,
+ Creeper,
+ Skull,
+ Flower,
+ Mojang,
+ Globe,
+ Piglin
+};
+
+
+
+
+
enum class BossBarColor
{
Pink,
diff --git a/src/Items/CMakeLists.txt b/src/Items/CMakeLists.txt
index 10635f831..0046386d0 100644
--- a/src/Items/CMakeLists.txt
+++ b/src/Items/CMakeLists.txt
@@ -5,6 +5,7 @@ target_sources(
ItemArmor.h
ItemAxe.h
+ ItemBanner.h
ItemBed.h
ItemBigFlower.h
ItemBoat.h
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;
+ });
+ }
+};
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index 69eccdefe..8c970692f 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -10,6 +10,7 @@
// Handlers:
#include "ItemArmor.h"
#include "ItemAxe.h"
+#include "ItemBanner.h"
#include "ItemBed.h"
#include "ItemBigFlower.h"
#include "ItemBoat.h"
@@ -112,6 +113,7 @@ cItemHandler * cItemHandler::CreateItemHandler(int a_ItemType)
default: return new cItemHandler(a_ItemType);
// Single item per handler, alphabetically sorted:
+ case E_ITEM_BANNER: return new cItemBannerHandler(a_ItemType);
case E_BLOCK_BIG_FLOWER: return new cItemBigFlowerHandler;
case E_BLOCK_CHEST: return new cItemChestHandler(a_ItemType);
case E_BLOCK_ENCHANTMENT_TABLE: return new cItemEnchantingTableHandler(a_ItemType);
diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp
index 89bc3f010..6b88fbe2a 100644
--- a/src/Protocol/Protocol_1_10.cpp
+++ b/src/Protocol/Protocol_1_10.cpp
@@ -35,6 +35,7 @@ Implements the 1.10 protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
+#include "../BlockEntities/BannerEntity.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
@@ -586,6 +587,18 @@ void cProtocol_1_10_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity
switch (a_BlockEntity.GetBlockType())
{
+ case E_BLOCK_WALL_BANNER:
+ case E_BLOCK_STANDING_BANNER:
+ {
+ auto & BannerEntity = static_cast<const cBannerEntity &>(a_BlockEntity);
+ Writer.AddInt("x", BannerEntity.GetPosX());
+ Writer.AddInt("y", BannerEntity.GetPosY());
+ Writer.AddInt("z", BannerEntity.GetPosZ());
+ Writer.AddString("id", "Banner");
+ Writer.AddInt("Base", static_cast<Int32>(BannerEntity.GetBaseColor()));
+ break;
+ }
+
case E_BLOCK_BEACON:
{
auto & BeaconEntity = static_cast<const cBeaconEntity &>(a_BlockEntity);
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index c8ba78e62..424116b94 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -30,6 +30,7 @@ Implements the 1.11 protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
+#include "../BlockEntities/BannerEntity.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/BedEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
@@ -416,6 +417,18 @@ void cProtocol_1_11_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity
switch (a_BlockEntity.GetBlockType())
{
+ case E_BLOCK_WALL_BANNER:
+ case E_BLOCK_STANDING_BANNER:
+ {
+ auto & BannerEntity = static_cast<const cBannerEntity &>(a_BlockEntity);
+ Writer.AddInt("x", BannerEntity.GetPosX());
+ Writer.AddInt("y", BannerEntity.GetPosY());
+ Writer.AddInt("z", BannerEntity.GetPosZ());
+ Writer.AddString("id", "Banner");
+ Writer.AddInt("Base", static_cast<Int32>(BannerEntity.GetBaseColor()));
+ break;
+ }
+
case E_BLOCK_BEACON:
{
auto & BeaconEntity = static_cast<const cBeaconEntity &>(a_BlockEntity);
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index 8e7b74614..1a1229f05 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -42,6 +42,7 @@ Implements the 1.8 protocol classes:
#include "../UI/Window.h"
#include "../UI/HorseWindow.h"
+#include "../BlockEntities/BannerEntity.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/EnchantingTableEntity.h"
@@ -1603,13 +1604,14 @@ void cProtocol_1_8_0::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
Byte Action = 0;
switch (a_BlockEntity.GetBlockType())
{
- case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
- case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
- case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity
- case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
- case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
- case E_BLOCK_BED: Action = 11; break; // Update bed color
-
+ case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
+ case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
+ case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity
+ case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
+ case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
+ case E_BLOCK_WALL_BANNER:
+ case E_BLOCK_STANDING_BANNER: Action = 6; break; // Update Banner
+ case E_BLOCK_BED: Action = 11; break; // Update bed color
case E_BLOCK_ENCHANTMENT_TABLE: Action = 0; break; // The ones with a action of 0 is just a workaround to send the block entities to a client.
case E_BLOCK_END_PORTAL: Action = 0; break; // Todo: 18.09.2020 - remove this when block entities are transmitted in the ChunkData packet - 12xx12
@@ -3217,6 +3219,18 @@ void cProtocol_1_8_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity &
switch (a_BlockEntity.GetBlockType())
{
+ case E_BLOCK_WALL_BANNER:
+ case E_BLOCK_STANDING_BANNER:
+ {
+ auto & BannerEntity = static_cast<const cBannerEntity &>(a_BlockEntity);
+ Writer.AddInt("x", BannerEntity.GetPosX());
+ Writer.AddInt("y", BannerEntity.GetPosY());
+ Writer.AddInt("z", BannerEntity.GetPosZ());
+ Writer.AddString("id", "Banner");
+ Writer.AddInt("Base", static_cast<Int32>(BannerEntity.GetBaseColor()));
+ break;
+ }
+
case E_BLOCK_BEACON:
{
auto & BeaconEntity = static_cast<const cBeaconEntity &>(a_BlockEntity);
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 88f8933be..916d3c206 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -45,6 +45,7 @@ Implements the 1.9 protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
#include "../UI/HorseWindow.h"
+#include "../BlockEntities/BannerEntity.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
@@ -1625,6 +1626,18 @@ void cProtocol_1_9_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity &
switch (a_BlockEntity.GetBlockType())
{
+ case E_BLOCK_WALL_BANNER:
+ case E_BLOCK_STANDING_BANNER:
+ {
+ auto & BannerEntity = static_cast<const cBannerEntity &>(a_BlockEntity);
+ Writer.AddInt("x", BannerEntity.GetPosX());
+ Writer.AddInt("y", BannerEntity.GetPosY());
+ Writer.AddInt("z", BannerEntity.GetPosZ());
+ Writer.AddString("id", "Banner");
+ Writer.AddInt("Base", static_cast<Int32>(BannerEntity.GetBaseColor()));
+ break;
+ }
+
case E_BLOCK_BEACON:
{
auto & BeaconEntity = static_cast<const cBeaconEntity &>(a_BlockEntity);
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 30e2a7815..7ce85616c 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -12,6 +12,7 @@
#include "../UUID.h"
#include "FastNBT.h"
+#include "../BlockEntities/BannerEntity.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/BedEntity.h"
#include "../BlockEntities/BrewingstandEntity.h"
@@ -205,6 +206,11 @@ public:
// Add tile-entity into NBT:
switch (a_Entity->GetBlockType())
{
+ // Banners:
+ case E_BLOCK_STANDING_BANNER:
+ case E_BLOCK_WALL_BANNER: AddBannerEntity (static_cast<cBannerEntity *> (a_Entity)); break;
+
+ // Others:
case E_BLOCK_BEACON: AddBeaconEntity (static_cast<cBeaconEntity *> (a_Entity)); break;
case E_BLOCK_BED: AddBedEntity (static_cast<cBedEntity *> (a_Entity)); break;
case E_BLOCK_BREWING_STAND: AddBrewingstandEntity (static_cast<cBrewingstandEntity *> (a_Entity)); break;
@@ -226,7 +232,6 @@ public:
case E_BLOCK_SIGN_POST: AddSignEntity (static_cast<cSignEntity *> (a_Entity)); break;
case E_BLOCK_TRAPPED_CHEST: AddChestEntity (static_cast<cChestEntity *> (a_Entity), a_Entity->GetBlockType()); break;
case E_BLOCK_WALLSIGN: AddSignEntity (static_cast<cSignEntity *> (a_Entity)); break;
-
default:
{
ASSERT(!"Unhandled block entity saved into Anvil");
@@ -366,6 +371,18 @@ public:
+ void AddBannerEntity(cBannerEntity * a_Entity)
+ {
+ mWriter.BeginCompound("");
+ AddBasicTileEntity(a_Entity,"Banner");
+ mWriter.AddInt("Base", static_cast<int>(a_Entity->GetBaseColor()));
+ mWriter.EndCompound();
+ }
+
+
+
+
+
void AddBeaconEntity(cBeaconEntity * a_Entity)
{
mWriter.BeginCompound("");
diff --git a/src/WorldStorage/NamespaceSerializer.cpp b/src/WorldStorage/NamespaceSerializer.cpp
index 088714cd1..28033fe29 100644
--- a/src/WorldStorage/NamespaceSerializer.cpp
+++ b/src/WorldStorage/NamespaceSerializer.cpp
@@ -140,7 +140,7 @@ std::string_view NamespaceSerializer::From(const Statistic a_ID)
-std::string_view NamespaceSerializer::From(eMonsterType a_ID)
+std::string_view NamespaceSerializer::From(const eMonsterType a_ID)
{
switch (a_ID)
{
@@ -222,6 +222,58 @@ std::string_view NamespaceSerializer::From(eMonsterType a_ID)
+std::string_view NamespaceSerializer::From(const BannerPattern a_Pattern)
+{
+ switch (a_Pattern)
+ {
+ case BannerPattern::BottomStripe: return "bs";
+ case BannerPattern::TopStripe: return "ts";
+ case BannerPattern::LeftStripe: return "ls";
+ case BannerPattern::RightStripe: return "rs";
+ case BannerPattern::CenterStripeVertical: return "cs";
+ case BannerPattern::MiddleStripeHorizontal: return "ms";
+ case BannerPattern::DownRightStripe: return "drs";
+ case BannerPattern::DownLeftStripe: return "dls";
+ case BannerPattern::SmallVerticalStripes: return "ss";
+ case BannerPattern::DiagonalCross: return "cr";
+ case BannerPattern::SquareCross: return "sc";
+ case BannerPattern::LeftOfDiagonal: return "ld";
+ case BannerPattern::RightOfUpsideDownDiagonal: return "rud";
+ case BannerPattern::LeftOfUpsideDownDiagonal: return "lud";
+ case BannerPattern::RightOfDiagonal: return "rd";
+ case BannerPattern::VerticalHalfLeft: return "vh";
+ case BannerPattern::VerticalHalfRight: return "vhr";
+ case BannerPattern::HorizontalHalfTop: return "hh";
+ case BannerPattern::HorizontalHalfBottom: return "hhb";
+ case BannerPattern::BottomLeftCorner: return "bl";
+ case BannerPattern::BottomRightCorner: return "br";
+ case BannerPattern::TopLeftCorner: return "tl";
+ case BannerPattern::TopRightCorner: return "tr";
+ case BannerPattern::BottomTriangle: return "bt";
+ case BannerPattern::TopTriangle: return "tt";
+ case BannerPattern::BottomTriangleSawtooth: return "bts";
+ case BannerPattern::TopTriangleSawtooth: return "tts";
+ case BannerPattern::MiddleCircle: return "mc";
+ case BannerPattern::MiddleRhombus: return "mr";
+ case BannerPattern::Border: return "bo";
+ case BannerPattern::CurlyBorder: return "cbo";
+ case BannerPattern::Brick: return "bri";
+ case BannerPattern::Gradient: return "gra";
+ case BannerPattern::GradientUpsideDown: return "gru";
+ case BannerPattern::Creeper: return "cre";
+ case BannerPattern::Skull: return "sku";
+ case BannerPattern::Flower: return "flo";
+ case BannerPattern::Mojang: return "moj";
+ case BannerPattern::Globe: return "glb";
+ case BannerPattern::Piglin: return "pig";
+ }
+ UNREACHABLE("Unsupported banner pattern");
+}
+
+
+
+
+
Statistic NamespaceSerializer::ToCustomStatistic(const std::string_view ID)
{
static const std::unordered_map<std::string_view, Statistic> CustomStatistics
diff --git a/src/WorldStorage/NamespaceSerializer.h b/src/WorldStorage/NamespaceSerializer.h
index 5b0093bcc..876db740f 100644
--- a/src/WorldStorage/NamespaceSerializer.h
+++ b/src/WorldStorage/NamespaceSerializer.h
@@ -1,7 +1,8 @@
#pragma once
-#include "../Registries/Statistics.h"
-#include "../Mobs/MonsterTypes.h"
+#include "Defines.h"
+#include "Mobs/MonsterTypes.h"
+#include "Registries/Statistics.h"
namespace NamespaceSerializer
{
@@ -16,6 +17,7 @@ namespace NamespaceSerializer
std::string_view From(Statistic a_ID);
std::string_view From(eMonsterType a_ID);
+ std::string_view From(BannerPattern a_ID);
Statistic ToCustomStatistic(std::string_view a_ID);
eMonsterType ToMonsterType(std::string_view a_ID);
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index e2a9b1539..dae1ca825 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -19,6 +19,7 @@
#include "../BlockType.h"
#include "../JsonUtils.h"
+#include "../BlockEntities/BannerEntity.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/BedEntity.h"
#include "../BlockEntities/BrewingstandEntity.h"
@@ -635,7 +636,11 @@ OwnedBlockEntity cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int
// Load the specific BlockEntity type:
switch (a_BlockType)
{
- // Specific entity loaders:
+ // Banners:
+ case E_BLOCK_STANDING_BANNER:
+ case E_BLOCK_WALL_BANNER: return LoadBannerFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
+
+ // Others:
case E_BLOCK_BEACON: return LoadBeaconFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_BED: return LoadBedFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_BREWING_STAND: return LoadBrewingstandFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
@@ -657,7 +662,6 @@ OwnedBlockEntity cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int
case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_WALLSIGN: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
-
default:
{
// All the other blocktypes should have no entities assigned to them. Report an error:
@@ -889,6 +893,29 @@ bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, con
+OwnedBlockEntity cWSSAnvil::LoadBannerFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos)
+{
+ static const AStringVector expectedTypes({"Banner", "minecraft:standingbanner","minecraft:wallbanner"});
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos))
+ {
+ return nullptr;
+ }
+
+ // Reads base color from NBT
+ int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Base");
+ if (CurrentLine >= 0)
+ {
+ const auto Color = static_cast<unsigned char>(a_NBT.GetInt(CurrentLine));
+ return std::make_unique<cBannerEntity>(a_BlockType, a_BlockMeta, a_Pos, m_World, Color);
+ }
+
+ return nullptr;
+}
+
+
+
+
+
OwnedBlockEntity cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos)
{
// Check if the data has a proper type:
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index d37bf2d25..971cbe3ef 100755..100644
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -157,6 +157,7 @@ protected:
The coordinates are used only for the log message. */
bool CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const AStringVector & a_ExpectedTypes, Vector3i a_Pos);
+ OwnedBlockEntity LoadBannerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadBeaconFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadBedFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadBrewingstandFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);