From 4e0ae63ec2ce5d4e1c1d434fcd9704b7131e6b41 Mon Sep 17 00:00:00 2001 From: Lukas Pioch Date: Mon, 5 Jun 2017 15:49:36 +0200 Subject: [PATCH] Added WriteBlockEntity to 1.10 and 1.11 and fixed mob spawner --- src/Protocol/Protocol_1_10.cpp | 114 ++++++++++++++++++++++++++++++++ src/Protocol/Protocol_1_10.h | 1 + src/Protocol/Protocol_1_11.cpp | 115 +++++++++++++++++++++++++++++++++ src/Protocol/Protocol_1_11.h | 1 + src/Protocol/Protocol_1_9.cpp | 4 +- src/Protocol/Protocol_1_9.h | 2 +- 6 files changed, 235 insertions(+), 2 deletions(-) diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index 4e716832e..16c1b3277 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -16,6 +16,8 @@ Implements the 1.10 protocol classes: #include "../Root.h" #include "../Server.h" +#include "../WorldStorage/FastNBT.h" + #include "../Entities/Boat.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" @@ -30,6 +32,12 @@ Implements the 1.10 protocol classes: #include "../Mobs/IncludeAllMonsters.h" +#include "../BlockEntities/BeaconEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" +#include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/MobSpawnerEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" + #include "Bindings/PluginManager.h" @@ -559,6 +567,112 @@ void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & +void cProtocol_1_10_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity) +{ + cFastNBTWriter Writer; + + switch (a_BlockEntity.GetBlockType()) + { + case E_BLOCK_BEACON: + { + auto & BeaconEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", BeaconEntity.GetPosX()); + Writer.AddInt("y", BeaconEntity.GetPosY()); + Writer.AddInt("z", BeaconEntity.GetPosZ()); + Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect()); + Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect()); + Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel()); + Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; + } + + case E_BLOCK_COMMAND_BLOCK: + { + auto & CommandBlockEntity = reinterpret_cast(a_BlockEntity); + Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this + Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult()); + Writer.AddInt("x", CommandBlockEntity.GetPosX()); + Writer.AddInt("y", CommandBlockEntity.GetPosY()); + Writer.AddInt("z", CommandBlockEntity.GetPosZ()); + Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str()); + // You can set custom names for windows in Vanilla + // For a command block, this would be the 'name' prepended to anything it outputs into global chat + // MCS doesn't have this, so just leave it @ '@'. (geddit?) + Writer.AddString("CustomName", "@"); + Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + if (!CommandBlockEntity.GetLastOutput().empty()) + { + Writer.AddString("LastOutput", Printf("{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str())); + } + break; + } + + case E_BLOCK_HEAD: + { + auto & MobHeadEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", MobHeadEntity.GetPosX()); + Writer.AddInt("y", MobHeadEntity.GetPosY()); + Writer.AddInt("z", MobHeadEntity.GetPosZ()); + Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF); + Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF); + Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + + // The new Block Entity format for a Mob Head. See: http://minecraft.gamepedia.com/Head#Block_entity + Writer.BeginCompound("Owner"); + Writer.AddString("Id", MobHeadEntity.GetOwnerUUID()); + Writer.AddString("Name", MobHeadEntity.GetOwnerName()); + Writer.BeginCompound("Properties"); + Writer.BeginList("textures", TAG_Compound); + Writer.BeginCompound(""); + Writer.AddString("Signature", MobHeadEntity.GetOwnerTextureSignature()); + Writer.AddString("Value", MobHeadEntity.GetOwnerTexture()); + Writer.EndCompound(); + Writer.EndList(); + Writer.EndCompound(); + Writer.EndCompound(); + break; + } + + case E_BLOCK_FLOWER_POT: + { + auto & FlowerPotEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", FlowerPotEntity.GetPosX()); + Writer.AddInt("y", FlowerPotEntity.GetPosY()); + Writer.AddInt("z", FlowerPotEntity.GetPosZ()); + Writer.AddInt("Item", static_cast(FlowerPotEntity.GetItem().m_ItemType)); + Writer.AddInt("Data", static_cast(FlowerPotEntity.GetItem().m_ItemDamage)); + Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; + } + + case E_BLOCK_MOB_SPAWNER: + { + auto & MobSpawnerEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", MobSpawnerEntity.GetPosX()); + Writer.AddInt("y", MobSpawnerEntity.GetPosY()); + Writer.AddInt("z", MobSpawnerEntity.GetPosZ()); + Writer.BeginCompound("SpawnData"); + Writer.AddString("id", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity())); + Writer.EndCompound(); + Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay()); + Writer.AddString("id", "MobSpawner"); + break; + } + + default: + { + break; + } + } + + Writer.Finish(); + a_Pkt.WriteBuf(Writer.GetResult().data(), Writer.GetResult().size()); +} + + + + + void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) { using namespace Metadata; diff --git a/src/Protocol/Protocol_1_10.h b/src/Protocol/Protocol_1_10.h index df64758e4..cd7c31fa0 100644 --- a/src/Protocol/Protocol_1_10.h +++ b/src/Protocol/Protocol_1_10.h @@ -34,4 +34,5 @@ public: protected: virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + virtual void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity) override; }; diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp index 7af7c5340..8f9a0b0b9 100644 --- a/src/Protocol/Protocol_1_11.cpp +++ b/src/Protocol/Protocol_1_11.cpp @@ -13,6 +13,8 @@ Implements the 1.11 protocol classes: #include "ProtocolRecognizer.h" #include "Packetizer.h" +#include "../WorldStorage/FastNBT.h" + #include "../Entities/Boat.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" @@ -27,6 +29,12 @@ Implements the 1.11 protocol classes: #include "../Mobs/IncludeAllMonsters.h" +#include "../BlockEntities/BeaconEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" +#include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/MobSpawnerEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" + #include "../Root.h" #include "../Server.h" #include "../ClientHandle.h" @@ -394,6 +402,113 @@ void cProtocol_1_11_0::SendSpawnMob(const cMonster & a_Mob) +void cProtocol_1_11_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity) +{ + cFastNBTWriter Writer; + + switch (a_BlockEntity.GetBlockType()) + { + case E_BLOCK_BEACON: + { + auto & BeaconEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", BeaconEntity.GetPosX()); + Writer.AddInt("y", BeaconEntity.GetPosY()); + Writer.AddInt("z", BeaconEntity.GetPosZ()); + Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect()); + Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect()); + Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel()); + Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; + } + + case E_BLOCK_COMMAND_BLOCK: + { + auto & CommandBlockEntity = reinterpret_cast(a_BlockEntity); + Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this + Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult()); + Writer.AddInt("x", CommandBlockEntity.GetPosX()); + Writer.AddInt("y", CommandBlockEntity.GetPosY()); + Writer.AddInt("z", CommandBlockEntity.GetPosZ()); + Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str()); + // You can set custom names for windows in Vanilla + // For a command block, this would be the 'name' prepended to anything it outputs into global chat + // MCS doesn't have this, so just leave it @ '@'. (geddit?) + Writer.AddString("CustomName", "@"); + Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + if (!CommandBlockEntity.GetLastOutput().empty()) + { + Writer.AddString("LastOutput", Printf("{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str())); + } + break; + } + + case E_BLOCK_HEAD: + { + auto & MobHeadEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", MobHeadEntity.GetPosX()); + Writer.AddInt("y", MobHeadEntity.GetPosY()); + Writer.AddInt("z", MobHeadEntity.GetPosZ()); + Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF); + Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF); + Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + + // The new Block Entity format for a Mob Head. See: http://minecraft.gamepedia.com/Head#Block_entity + Writer.BeginCompound("Owner"); + Writer.AddString("Id", MobHeadEntity.GetOwnerUUID()); + Writer.AddString("Name", MobHeadEntity.GetOwnerName()); + Writer.BeginCompound("Properties"); + Writer.BeginList("textures", TAG_Compound); + Writer.BeginCompound(""); + Writer.AddString("Signature", MobHeadEntity.GetOwnerTextureSignature()); + Writer.AddString("Value", MobHeadEntity.GetOwnerTexture()); + Writer.EndCompound(); + Writer.EndList(); + Writer.EndCompound(); + Writer.EndCompound(); + break; + } + + case E_BLOCK_FLOWER_POT: + { + auto & FlowerPotEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", FlowerPotEntity.GetPosX()); + Writer.AddInt("y", FlowerPotEntity.GetPosY()); + Writer.AddInt("z", FlowerPotEntity.GetPosZ()); + Writer.AddInt("Item", static_cast(FlowerPotEntity.GetItem().m_ItemType)); + Writer.AddInt("Data", static_cast(FlowerPotEntity.GetItem().m_ItemDamage)); + Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; + } + + case E_BLOCK_MOB_SPAWNER: + { + auto & MobSpawnerEntity = reinterpret_cast(a_BlockEntity); + Writer.AddInt("x", MobSpawnerEntity.GetPosX()); + Writer.AddInt("y", MobSpawnerEntity.GetPosY()); + Writer.AddInt("z", MobSpawnerEntity.GetPosZ()); + Writer.BeginCompound("SpawnData"); + Writer.AddString("id", "minecraft:" + cMonster::MobTypeToVanillaNBT(MobSpawnerEntity.GetEntity())); + Writer.EndCompound(); + Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay()); + Writer.AddString("id", "MobSpawner"); + break; + } + + default: + { + break; + } + } + + Writer.Finish(); + a_Pkt.WriteBuf(Writer.GetResult().data(), Writer.GetResult().size()); +} + + + + + + void cProtocol_1_11_0::SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol_1_11.h b/src/Protocol/Protocol_1_11.h index a3413ecdf..128b7f7e4 100644 --- a/src/Protocol/Protocol_1_11.h +++ b/src/Protocol/Protocol_1_11.h @@ -41,6 +41,7 @@ protected: virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override; + virtual void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity) override; }; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index da8965be0..d1b717bd0 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -3501,7 +3501,9 @@ void cProtocol_1_9_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & Writer.AddInt("x", MobSpawnerEntity.GetPosX()); Writer.AddInt("y", MobSpawnerEntity.GetPosY()); Writer.AddInt("z", MobSpawnerEntity.GetPosZ()); - Writer.AddString("EntityId", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity())); + Writer.BeginCompound("SpawnData"); + Writer.AddString("id", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity())); + Writer.EndCompound(); Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay()); Writer.AddString("id", "MobSpawner"); break; diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index 99fc87b69..d6533c5da 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -269,7 +269,7 @@ protected: void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity); /** Writes the block entity data for the specified block entity into the packet. */ - void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity); + virtual void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity); /** Types used within metadata */ enum eMetadataType