From 3d398baf355fd0dee0e282a73c61fe79f288db8f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 13 Mar 2015 23:05:06 +0000 Subject: cPainting saving implemented Additionally, it now inherits from cHangingEntity. --- src/Entities/HangingEntity.cpp | 2 -- src/Entities/HangingEntity.h | 13 +++++++++---- src/Entities/ItemFrame.cpp | 11 +++++++++++ src/Entities/ItemFrame.h | 1 + src/Entities/Painting.cpp | 18 ++++-------------- src/Entities/Painting.h | 18 ++++++------------ src/Items/ItemPainting.h | 19 +++---------------- src/Protocol/Protocol17x.cpp | 2 +- src/Protocol/Protocol18x.cpp | 10 +--------- src/WorldStorage/NBTChunkSerializer.cpp | 30 ++++++++++++++++-------------- src/WorldStorage/NBTChunkSerializer.h | 2 ++ src/WorldStorage/WSSAnvil.cpp | 28 ++++++++++++++++++++++++++++ src/WorldStorage/WSSAnvil.h | 1 + 13 files changed, 83 insertions(+), 72 deletions(-) diff --git a/src/Entities/HangingEntity.cpp b/src/Entities/HangingEntity.cpp index a3d05204a..a37d8702e 100644 --- a/src/Entities/HangingEntity.cpp +++ b/src/Entities/HangingEntity.cpp @@ -24,8 +24,6 @@ cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_Facing, do void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle) { SetYaw(GetProtocolFacing() * 90); - a_ClientHandle.SendSpawnObject(*this, 71, GetProtocolFacing(), (Byte)GetYaw(), (Byte)GetPitch()); - a_ClientHandle.SendEntityMetadata(*this); } diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h index de93a73fe..8c9e93622 100644 --- a/src/Entities/HangingEntity.h +++ b/src/Entities/HangingEntity.h @@ -41,10 +41,14 @@ public: m_Facing = a_Facing; } -private: +protected: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override {} + virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override + { + UNUSED(a_Dt); + UNUSED(a_Chunk); + } /** Converts protocol hanging item facing to eBlockFace values */ inline static eBlockFace ProtocolFaceToBlockFace(Byte a_ProtocolFace) @@ -84,8 +88,9 @@ private: case BLOCK_FACE_XP: Dir = 3; break; default: { - LOGINFO("Invalid facing (%d) in a cHangingEntity, adjusting to BLOCK_FACE_XP.", a_BlockFace); - // Uncomment when entities are initialised with their real data, instead of dummy values: ASSERT(!"Tried to convert a bad facing!"); + // Uncomment when entities are initialised with their real data, instead of dummy values: + // LOGINFO("Invalid facing (%d) in a cHangingEntity, adjusting to BLOCK_FACE_XP.", a_BlockFace); + // ASSERT(!"Tried to convert a bad facing!"); Dir = cHangingEntity::BlockFaceToProtocolFace(BLOCK_FACE_XP); } diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp index dfffcd3ed..4e6e38f1f 100644 --- a/src/Entities/ItemFrame.cpp +++ b/src/Entities/ItemFrame.cpp @@ -92,3 +92,14 @@ void cItemFrame::GetDrops(cItems & a_Items, cEntity * a_Killer) + +void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle) +{ + super::SpawnOn(a_ClientHandle); + a_ClientHandle.SendSpawnObject(*this, 71, GetProtocolFacing(), (Byte)GetYaw(), (Byte)GetPitch()); + a_ClientHandle.SendEntityMetadata(*this); +} + + + + diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h index ced8c37af..2444b26a3 100644 --- a/src/Entities/ItemFrame.h +++ b/src/Entities/ItemFrame.h @@ -42,6 +42,7 @@ private: virtual void OnRightClicked(cPlayer & a_Player) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; cItem m_Item; Byte m_ItemRotation; diff --git a/src/Entities/Painting.cpp b/src/Entities/Painting.cpp index 6f6277f28..02a8f6ed0 100644 --- a/src/Entities/Painting.cpp +++ b/src/Entities/Painting.cpp @@ -10,10 +10,9 @@ -cPainting::cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z) - : cEntity(etPainting, a_X, a_Y, a_Z, 1, 1), - m_Name(a_Name), - m_Direction(a_Direction) +cPainting::cPainting(const AString & a_Name, eBlockFace a_Direction, double a_X, double a_Y, double a_Z) + : cHangingEntity(etPainting, a_Direction, a_X, a_Y, a_Z), + m_Name(a_Name) { } @@ -24,6 +23,7 @@ cPainting::cPainting(const AString & a_Name, int a_Direction, double a_X, double void cPainting::SpawnOn(cClientHandle & a_Client) { + super::SpawnOn(a_Client); a_Client.SendPaintingSpawn(*this); } @@ -31,16 +31,6 @@ void cPainting::SpawnOn(cClientHandle & a_Client) -void cPainting::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) -{ - UNUSED(a_Dt); - UNUSED(a_Chunk); -} - - - - - void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer) { if ((a_Killer != nullptr) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h index 6e8a382fc..20968d4f0 100644 --- a/src/Entities/Painting.h +++ b/src/Entities/Painting.h @@ -1,7 +1,7 @@ #pragma once -#include "Entity.h" +#include "HangingEntity.h" @@ -9,9 +9,9 @@ // tolua_begin class cPainting : - public cEntity + public cHangingEntity { - typedef cEntity super; + typedef cHangingEntity super; public: @@ -19,19 +19,14 @@ public: CLASS_PROTODEF(cPainting) - cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z); + cPainting(const AString & a_Name, eBlockFace a_Direction, double a_X, double a_Y, double a_Z); - // tolua_begin - - const AString & GetName(void) const { return m_Name; } - int GetDirection(void) const { return m_Direction; } - - // tolua_end + /** Returns the protocol name of the painting */ + const AString & GetName(void) const { return m_Name; } // tolua_export private: virtual void SpawnOn(cClientHandle & a_Client) override; - virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override { @@ -40,7 +35,6 @@ private: } AString m_Name; - int m_Direction; }; // tolua_export diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h index a2a77ce21..d6f2e24b4 100644 --- a/src/Items/ItemPainting.h +++ b/src/Items/ItemPainting.h @@ -21,30 +21,17 @@ public: virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override { - if (a_Dir == BLOCK_FACE_NONE) + if ((a_Dir == BLOCK_FACE_NONE) || (a_Dir == BLOCK_FACE_YM) || (a_Dir == BLOCK_FACE_YP)) { - // Client sends this if clicked on top or bottom face + // Paintings can't be flatly placed return false; } AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again if (Block == E_BLOCK_AIR) { - int Dir = 0; - - // The client uses different values for painting directions and block faces. Our constants are for the block faces, so we convert them here to painting faces - switch (a_Dir) - { - case BLOCK_FACE_ZP: break; // Initialised to zero - case BLOCK_FACE_ZM: Dir = 2; break; - case BLOCK_FACE_XM: Dir = 1; break; - case BLOCK_FACE_XP: Dir = 3; break; - default: ASSERT(!"Unhandled block face when trying spawn painting!"); return false; - } - static const struct // Define all the possible painting titles { AString Title; @@ -78,7 +65,7 @@ public: { "BurningSkull" } }; - cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, Dir, a_BlockX, a_BlockY, a_BlockZ); + cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, a_Dir, a_BlockX, a_BlockY, a_BlockZ); Painting->Initialize(*a_World); if (!a_Player->IsGameModeCreative()) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f78c2e54b..9abe81238 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -637,7 +637,7 @@ void cProtocol172::SendPaintingSpawn(const cPainting & a_Painting) Pkt.WriteInt(static_cast(a_Painting.GetPosX())); Pkt.WriteInt(static_cast(a_Painting.GetPosY())); Pkt.WriteInt(static_cast(a_Painting.GetPosZ())); - Pkt.WriteInt(a_Painting.GetDirection()); + Pkt.WriteInt(a_Painting.GetProtocolFacing()); } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index 22280f800..52c369200 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -632,19 +632,11 @@ void cProtocol180::SendPaintingSpawn(const cPainting & a_Painting) double PosY = a_Painting.GetPosY(); double PosZ = a_Painting.GetPosZ(); - switch (a_Painting.GetDirection()) - { - case 0: PosZ += 1; break; - case 1: PosX -= 1; break; - case 2: PosZ -= 1; break; - case 3: PosX += 1; break; - } - cPacketizer Pkt(*this, 0x10); // Spawn Painting packet Pkt.WriteVarInt(a_Painting.GetUniqueID()); Pkt.WriteString(a_Painting.GetName().c_str()); Pkt.WritePosition((int)PosX, (int)PosY, (int)PosZ); - Pkt.WriteChar(a_Painting.GetDirection()); + Pkt.WriteChar(a_Painting.GetProtocolFacing()); } diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 4f78dd245..10231ae3b 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -36,20 +36,9 @@ #include "../Entities/ExpOrb.h" #include "../Entities/HangingEntity.h" #include "../Entities/ItemFrame.h" +#include "../Entities/Painting.h" -#include "../Mobs/Monster.h" -#include "../Mobs/Bat.h" -#include "../Mobs/Creeper.h" -#include "../Mobs/Enderman.h" -#include "../Mobs/Horse.h" -#include "../Mobs/MagmaCube.h" -#include "../Mobs/Sheep.h" -#include "../Mobs/Slime.h" -#include "../Mobs/Skeleton.h" -#include "../Mobs/Villager.h" -#include "../Mobs/Wither.h" -#include "../Mobs/Wolf.h" -#include "../Mobs/Zombie.h" +#include "../Mobs/IncludeAllMonsters.h" @@ -776,6 +765,19 @@ void cNBTChunkSerializer::AddItemFrameEntity(cItemFrame * a_ItemFrame) +void cNBTChunkSerializer::AddPaintingEntity(cPainting * a_Painting) +{ + m_Writer.BeginCompound(""); + AddBasicEntity(a_Painting, "Painting"); + AddHangingEntity(a_Painting); + m_Writer.AddString("Motive", a_Painting->GetName()); + m_Writer.EndCompound(); +} + + + + + void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart) { m_Writer.BeginList("Items", TAG_Compound); @@ -874,7 +876,7 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity) case cEntity::etTNT: AddTNTEntity ((cTNTEntity *) a_Entity); break; case cEntity::etExpOrb: AddExpOrbEntity ((cExpOrb *) a_Entity); break; case cEntity::etItemFrame: AddItemFrameEntity ((cItemFrame *) a_Entity); break; - case cEntity::etPainting: /* TODO */ break; + case cEntity::etPainting: AddPaintingEntity (reinterpret_cast(a_Entity)); break; case cEntity::etPlayer: return; // Players aren't saved into the world default: { diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 4c066b9af..f30cd59d5 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -48,6 +48,7 @@ class cTNTEntity; class cExpOrb; class cHangingEntity; class cItemFrame; +class cPainting; class cEntityEffect; @@ -123,6 +124,7 @@ protected: void AddTNTEntity (cTNTEntity * a_TNT); void AddExpOrbEntity (cExpOrb * a_ExpOrb); void AddItemFrameEntity (cItemFrame * a_ItemFrame); + void AddPaintingEntity (cPainting * a_Painting); void AddMinecartChestContents(cMinecartWithChest * a_Minecart); diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 0aa26834c..7244bcb73 100755 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -50,6 +50,7 @@ #include "../Entities/ExpOrb.h" #include "../Entities/HangingEntity.h" #include "../Entities/ItemFrame.h" +#include "../Entities/Painting.h" #include "../Protocol/MojangAPI.h" #include "Server.h" @@ -1337,6 +1338,10 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a { LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx); } + else if (strncmp(a_IDTag, "Painting", a_IDTagLength) == 0) + { + LoadPaintingFromNBT(a_Entities, a_NBT, a_EntityTagIdx); + } else if (strncmp(a_IDTag, "PrimedTnt", a_IDTagLength) == 0) { LoadTNTFromNBT(a_Entities, a_NBT, a_EntityTagIdx); @@ -1808,6 +1813,29 @@ void cWSSAnvil::LoadItemFrameFromNBT(cEntityList & a_Entities, const cParsedNBT +void cWSSAnvil::LoadPaintingFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) +{ + // Load painting name: + int MotiveTag = a_NBT.FindChildByName(a_TagIdx, "Motive"); + if ((MotiveTag < 0) || (a_NBT.GetType(MotiveTag) != TAG_String)) + { + return; + } + + std::unique_ptr Painting(new cPainting(a_NBT.GetString(MotiveTag), BLOCK_FACE_NONE, 0.0, 0.0, 0.0)); + if (!LoadEntityBaseFromNBT(*Painting.get(), a_NBT, a_TagIdx)) + { + return; + } + + LoadHangingFromNBT(*Painting.get(), a_NBT, a_TagIdx); + a_Entities.push_back(Painting.release()); +} + + + + + void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Arrow(new cArrowEntity(nullptr, 0, 0, 0, Vector3d(0, 0, 0))); diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index 362796614..892645785 100755 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -166,6 +166,7 @@ protected: void LoadExpOrbFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadHangingFromNBT (cHangingEntity & a_Hanging, const cParsedNBT & a_NBT, int a_TagIdx); void LoadItemFrameFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadPaintingFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartCFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); -- cgit v1.2.3