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(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(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(a_BlockType, a_BlockMeta, a_Pos, a_World); + + // Others: case E_BLOCK_BEACON: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_BED: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_BREWING_STAND: return std::make_unique(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(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(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(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(BannerEntity.GetBaseColor())); + break; + } + case E_BLOCK_BEACON: { auto & BeaconEntity = static_cast(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(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(BannerEntity.GetBaseColor())); + break; + } + case E_BLOCK_BEACON: { auto & BeaconEntity = static_cast(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(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(BannerEntity.GetBaseColor())); + break; + } + case E_BLOCK_BEACON: { auto & BeaconEntity = static_cast(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(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(BannerEntity.GetBaseColor())); + break; + } + case E_BLOCK_BEACON: { auto & BeaconEntity = static_cast(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 (a_Entity)); break; + + // Others: case E_BLOCK_BEACON: AddBeaconEntity (static_cast (a_Entity)); break; case E_BLOCK_BED: AddBedEntity (static_cast (a_Entity)); break; case E_BLOCK_BREWING_STAND: AddBrewingstandEntity (static_cast (a_Entity)); break; @@ -226,7 +232,6 @@ public: case E_BLOCK_SIGN_POST: AddSignEntity (static_cast (a_Entity)); break; case E_BLOCK_TRAPPED_CHEST: AddChestEntity (static_cast (a_Entity), a_Entity->GetBlockType()); break; case E_BLOCK_WALLSIGN: AddSignEntity (static_cast (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(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 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(a_NBT.GetInt(CurrentLine)); + return std::make_unique(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 old mode 100755 new mode 100644 index d37bf2d25..971cbe3ef --- 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);