summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2020-04-20 21:46:04 +0200
committerTiger Wang <ziwei.tiger@outlook.com>2020-05-01 00:04:56 +0200
commit0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d (patch)
treeafe3041898d51e53ca693861564792e0d828774e /src/Protocol
parentNBT: Dynamic list-max-count protection. (#4697) (diff)
downloadcuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.tar
cuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.tar.gz
cuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.tar.bz2
cuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.tar.lz
cuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.tar.xz
cuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.tar.zst
cuberite-0b9b7bc1a8d5cf6f92b802dc376a189ef066e62d.zip
Diffstat (limited to '')
-rw-r--r--src/Protocol/Protocol.h8
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp43
-rw-r--r--src/Protocol/ProtocolRecognizer.h8
-rw-r--r--src/Protocol/Protocol_1_11.cpp2
-rw-r--r--src/Protocol/Protocol_1_8.cpp353
-rw-r--r--src/Protocol/Protocol_1_8.h19
-rw-r--r--src/Protocol/Protocol_1_9.cpp139
-rw-r--r--src/Protocol/Protocol_1_9.h7
8 files changed, 212 insertions, 367 deletions
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index eb7b3cc9a..fc1a1d9d3 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -185,7 +185,6 @@ public:
virtual void SendLoginSuccess (void) = 0;
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) = 0;
virtual void SendPaintingSpawn (const cPainting & a_Painting) = 0;
- virtual void SendPickupSpawn (const cPickup & a_Pickup) = 0;
virtual void SendPlayerAbilities (void) = 0;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0;
virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) = 0;
@@ -215,10 +214,8 @@ public:
virtual void SendSetRawTitle (const AString & a_Title) = 0;
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) = 0;
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0;
- virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0;
+ virtual void SendSpawnEntity (const cEntity & a_Entity) = 0;
virtual void SendSpawnMob (const cMonster & a_Mob) = 0;
- virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData) = 0;
- virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) = 0;
virtual void SendStatistics (const cStatManager & a_Manager) = 0;
virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0;
virtual void SendTeleportEntity (const cEntity & a_Entity) = 0;
@@ -259,9 +256,6 @@ protected:
/** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */
virtual UInt32 GetPacketID(ePacketType a_Packet) = 0;
- /** Converts eMonsterType to protocol-specific mob types */
- virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) = 0;
-
/** A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it. */
virtual void SendData(const char * a_Data, size_t a_Size) = 0;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index ee6d61cea..d5f40b19b 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -550,16 +550,6 @@ void cProtocolRecognizer::SendPaintingSpawn(const cPainting & a_Painting)
-void cProtocolRecognizer::SendPickupSpawn(const cPickup & a_Pickup)
-{
- ASSERT(m_Protocol != nullptr);
- m_Protocol->SendPickupSpawn(a_Pickup);
-}
-
-
-
-
-
void cProtocolRecognizer::SendPlayerAbilities(void)
{
ASSERT(m_Protocol != nullptr);
@@ -830,10 +820,10 @@ void cProtocolRecognizer::SendSoundParticleEffect(const EffectID a_EffectID, int
-void cProtocolRecognizer::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
+void cProtocolRecognizer::SendSpawnEntity(const cEntity & a_Entity)
{
ASSERT(m_Protocol != nullptr);
- m_Protocol->SendSpawnFallingBlock(a_FallingBlock);
+ m_Protocol->SendSpawnEntity(a_Entity);
}
@@ -850,26 +840,6 @@ void cProtocolRecognizer::SendSpawnMob(const cMonster & a_Mob)
-void cProtocolRecognizer::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData)
-{
- ASSERT(m_Protocol != nullptr);
- m_Protocol->SendSpawnObject(a_Entity, a_ObjectType, a_ObjectData);
-}
-
-
-
-
-
-void cProtocolRecognizer::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType)
-{
- ASSERT(m_Protocol != nullptr);
- m_Protocol->SendSpawnVehicle(a_Vehicle, a_VehicleType, a_VehicleSubType);
-}
-
-
-
-
-
void cProtocolRecognizer::SendStatistics(const cStatManager & a_Manager)
{
ASSERT(m_Protocol != nullptr);
@@ -1020,15 +990,6 @@ AString cProtocolRecognizer::GetAuthServerID(void)
-UInt32 cProtocolRecognizer::GetProtocolMobType(eMonsterType a_MobType)
-{
- return 0;
-}
-
-
-
-
-
void cProtocolRecognizer::SendData(const char * a_Data, size_t a_Size)
{
// This is used only when handling the server ping
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 9caa891a4..a658a95d9 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -89,7 +89,6 @@ public:
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
- virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override;
@@ -117,10 +116,8 @@ public:
virtual void SendSetRawTitle (const AString & a_Title) override;
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
- virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
+ virtual void SendSpawnEntity (const cEntity & a_Entity) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
- virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData) override;
- virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override;
virtual void SendStatistics (const cStatManager & a_Manager) override;
virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
virtual void SendTeleportEntity (const cEntity & a_Entity) override;
@@ -156,9 +153,6 @@ protected:
/** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */
virtual UInt32 GetPacketID(ePacketType a_PacketType) override;
- /** Converts eMonsterType to protocol-specific mob types */
- virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override;
-
// Packet handlers while in status state (m_InPingForUnrecognizedVersion == true)
void HandlePacketStatusRequest();
void HandlePacketStatusPing();
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index 7ce4db539..3ccb76d39 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -544,7 +544,7 @@ UInt32 cProtocol_1_11_0::GetProtocolMobType(eMonsterType a_MobType)
switch (a_MobType)
{
// Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
- case mtInvalidType: return 52;
+ case mtInvalidType: return 53;
case mtBat: return 65;
case mtBlaze: return 61;
case mtCaveSpider: return 59;
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index d402a41ec..a2ea4eceb 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -31,6 +31,7 @@ Implements the 1.8 protocol classes:
#include "../Entities/ExpOrb.h"
#include "../Entities/Minecart.h"
#include "../Entities/FallingBlock.h"
+#include "../Entities/Floater.h"
#include "../Entities/Painting.h"
#include "../Entities/Pickup.h"
#include "../Entities/Player.h"
@@ -852,28 +853,6 @@ void cProtocol_1_8_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_Da
-void cProtocol_1_8_0::SendPickupSpawn(const cPickup & a_Pickup)
-{
- ASSERT(m_State == 3); // In game mode?
-
- {
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_Pickup.GetUniqueID());
- Pkt.WriteBEUInt8(2); // Type = Pickup
- Pkt.WriteFPInt(a_Pickup.GetPosX());
- Pkt.WriteFPInt(a_Pickup.GetPosY());
- Pkt.WriteFPInt(a_Pickup.GetPosZ());
- Pkt.WriteByteAngle(a_Pickup.GetYaw());
- Pkt.WriteByteAngle(a_Pickup.GetPitch());
- Pkt.WriteBEInt32(0); // No object data
- }
- SendEntityMetadata(a_Pickup);
-}
-
-
-
-
-
void cProtocol_1_8_0::SendPlayerAbilities(void)
{
ASSERT(m_State == 3); // In game mode?
@@ -1370,23 +1349,45 @@ void cProtocol_1_8_0::SendSoundParticleEffect(const EffectID a_EffectID, int a_S
-void cProtocol_1_8_0::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
+void cProtocol_1_8_0::SendSpawnEntity(const cEntity & a_Entity)
{
- ASSERT(m_State == 3); // In game mode?
+ Int32 EntityData = /* Default: velocity present flag */ 1;
+ const auto EntityType = GetProtocolEntityType(a_Entity);
+
+ if (a_Entity.IsMinecart())
+ {
+ const auto & Cart = static_cast<const cMinecart &>(a_Entity);
+ EntityData = static_cast<Int32>(Cart.GetPayload());
+ }
+ else if (a_Entity.IsItemFrame())
+ {
+ const auto & Frame = static_cast<const cItemFrame &>(a_Entity);
+ EntityData = static_cast<Int32>(Frame.GetProtocolFacing());
+ }
+ else if (a_Entity.IsFallingBlock())
+ {
+ const auto & Block = static_cast<const cFallingBlock &>(a_Entity);
+ EntityData = Block.GetBlockType() | (static_cast<Int32>(Block.GetBlockMeta()) << 12);
+ }
+ else if (a_Entity.IsFloater())
+ {
+ const auto & Floater = static_cast<const cFloater &>(a_Entity);
+ EntityData = static_cast<Int32>(Floater.GetOwnerID());
+ }
+ else if (a_Entity.IsProjectile())
+ {
+ using PType = cProjectileEntity::eKind;
+ const auto & Projectile = static_cast<const cProjectileEntity &>(a_Entity);
+
+ if (Projectile.GetProjectileKind() == PType::pkArrow)
+ {
+ const auto & Arrow = static_cast<const cArrowEntity &>(Projectile);
+ EntityData = static_cast<Int32>(Arrow.GetCreatorUniqueID() + 1);
+ }
+ }
cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_FallingBlock.GetUniqueID());
- Pkt.WriteBEUInt8(70); // Falling block
- Vector3d LastSentPos = a_FallingBlock.GetLastSentPos();
- Pkt.WriteFPInt(LastSentPos.x);
- Pkt.WriteFPInt(LastSentPos.y);
- Pkt.WriteFPInt(LastSentPos.z);
- Pkt.WriteByteAngle(a_FallingBlock.GetYaw());
- Pkt.WriteByteAngle(a_FallingBlock.GetPitch());
- Pkt.WriteBEInt32(static_cast<Int32>(a_FallingBlock.GetBlockType()) | (static_cast<Int32>(a_FallingBlock.GetBlockMeta()) << 12));
- Pkt.WriteBEInt16(static_cast<Int16>(a_FallingBlock.GetSpeedX() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_FallingBlock.GetSpeedY() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_FallingBlock.GetSpeedZ() * 400));
+ WriteEntitySpawn(Pkt, a_Entity, EntityType, EntityData);
}
@@ -1418,64 +1419,6 @@ void cProtocol_1_8_0::SendSpawnMob(const cMonster & a_Mob)
-void cProtocol_1_8_0::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData)
-{
- ASSERT(m_State == 3); // In game mode?
- double PosX = a_Entity.GetPosX();
- double PosZ = a_Entity.GetPosZ();
- double Yaw = a_Entity.GetYaw();
- if (a_ObjectType == 71)
- {
- FixItemFramePositions(a_ObjectData, PosX, PosZ, Yaw);
- }
-
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEUInt8(static_cast<UInt8>(a_ObjectType));
- Pkt.WriteFPInt(PosX);
- Pkt.WriteFPInt(a_Entity.GetPosY());
- Pkt.WriteFPInt(PosZ);
- Pkt.WriteByteAngle(a_Entity.GetPitch());
- Pkt.WriteByteAngle(Yaw);
- Pkt.WriteBEInt32(a_ObjectData);
- if (a_ObjectData != 0)
- {
- Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400));
- }
-}
-
-
-
-
-
-void cProtocol_1_8_0::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_Vehicle.GetUniqueID());
- Pkt.WriteBEUInt8(static_cast<UInt8>(a_VehicleType));
- Vector3d LastSentPos = a_Vehicle.GetLastSentPos();
- Pkt.WriteFPInt(LastSentPos.x);
- Pkt.WriteFPInt(LastSentPos.y);
- Pkt.WriteFPInt(LastSentPos.z);
- Pkt.WriteByteAngle(a_Vehicle.GetPitch());
- Pkt.WriteByteAngle(a_Vehicle.GetYaw());
- Pkt.WriteBEInt32(a_VehicleSubType);
- if (a_VehicleSubType != 0)
- {
- Pkt.WriteBEInt16(static_cast<Int16>(a_Vehicle.GetSpeedX() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Vehicle.GetSpeedY() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Vehicle.GetSpeedZ() * 400));
- }
-}
-
-
-
-
-
void cProtocol_1_8_0::SendStatistics(const cStatManager & a_Manager)
{
ASSERT(m_State == 3); // In game mode?
@@ -1808,70 +1751,70 @@ bool cProtocol_1_8_0::CompressPacket(const AString & a_Packet, AString & a_Compr
int cProtocol_1_8_0::GetParticleID(const AString & a_ParticleName)
{
- static std::map<AString, int> ParticleMap;
- if (ParticleMap.empty())
+ static const std::unordered_map<AString, int> ParticleMap
{
// Initialize the ParticleMap:
- ParticleMap["explode"] = 0;
- ParticleMap["largeexplode"] = 1;
- ParticleMap["hugeexplosion"] = 2;
- ParticleMap["fireworksspark"] = 3;
- ParticleMap["bubble"] = 4;
- ParticleMap["splash"] = 5;
- ParticleMap["wake"] = 6;
- ParticleMap["suspended"] = 7;
- ParticleMap["depthsuspend"] = 8;
- ParticleMap["crit"] = 9;
- ParticleMap["magiccrit"] = 10;
- ParticleMap["smoke"] = 11;
- ParticleMap["largesmoke"] = 12;
- ParticleMap["spell"] = 13;
- ParticleMap["instantspell"] = 14;
- ParticleMap["mobspell"] = 15;
- ParticleMap["mobspellambient"] = 16;
- ParticleMap["witchmagic"] = 17;
- ParticleMap["dripwater"] = 18;
- ParticleMap["driplava"] = 19;
- ParticleMap["angryvillager"] = 20;
- ParticleMap["happyvillager"] = 21;
- ParticleMap["townaura"] = 22;
- ParticleMap["note"] = 23;
- ParticleMap["portal"] = 24;
- ParticleMap["enchantmenttable"] = 25;
- ParticleMap["flame"] = 26;
- ParticleMap["lava"] = 27;
- ParticleMap["footstep"] = 28;
- ParticleMap["cloud"] = 29;
- ParticleMap["reddust"] = 30;
- ParticleMap["snowballpoof"] = 31;
- ParticleMap["snowshovel"] = 32;
- ParticleMap["slime"] = 33;
- ParticleMap["heart"] = 34;
- ParticleMap["barrier"] = 35;
- ParticleMap["iconcrack"] = 36;
- ParticleMap["blockcrack"] = 37;
- ParticleMap["blockdust"] = 38;
- ParticleMap["droplet"] = 39;
- ParticleMap["take"] = 40;
- ParticleMap["mobappearance"] = 41;
- ParticleMap["dragonbreath"] = 42;
- ParticleMap["endrod"] = 43;
- ParticleMap["damageindicator"] = 44;
- ParticleMap["sweepattack"] = 45;
- ParticleMap["fallingdust"] = 46;
- ParticleMap["totem"] = 47;
- ParticleMap["spit"] = 48;
- }
-
- AString ParticleName = StrToLower(a_ParticleName);
- if (ParticleMap.find(ParticleName) == ParticleMap.end())
+ { "explode", 0 },
+ { "largeexplode", 1 },
+ { "hugeexplosion", 2 },
+ { "fireworksspark", 3 },
+ { "bubble", 4 },
+ { "splash", 5 },
+ { "wake", 6 },
+ { "suspended", 7 },
+ { "depthsuspend", 8 },
+ { "crit", 9 },
+ { "magiccrit", 10 },
+ { "smoke", 11 },
+ { "largesmoke", 12 },
+ { "spell", 13 },
+ { "instantspell", 14 },
+ { "mobspell", 15 },
+ { "mobspellambient", 16 },
+ { "witchmagic", 17 },
+ { "dripwater", 18 },
+ { "driplava", 19 },
+ { "angryvillager", 20 },
+ { "happyvillager", 21 },
+ { "townaura", 22 },
+ { "note", 23 },
+ { "portal", 24 },
+ { "enchantmenttable", 25 },
+ { "flame", 26 },
+ { "lava", 27 },
+ { "footstep", 28 },
+ { "cloud", 29 },
+ { "reddust", 30 },
+ { "snowballpoof", 31 },
+ { "snowshovel", 32 },
+ { "slime", 33 },
+ { "heart", 34 },
+ { "barrier", 35 },
+ { "iconcrack", 36 },
+ { "blockcrack", 37 },
+ { "blockdust", 38 },
+ { "droplet", 39 },
+ { "take", 40 },
+ { "mobappearance", 41 },
+ { "dragonbreath", 42 },
+ { "endrod", 43 },
+ { "damageindicator", 44 },
+ { "sweepattack", 45 },
+ { "fallingdust", 46 },
+ { "totem", 47 },
+ { "spit", 48 }
+ };
+
+ const auto ParticleName = StrToLower(a_ParticleName);
+ const auto FindResult = ParticleMap.find(ParticleName);
+ if (FindResult == ParticleMap.end())
{
LOGWARNING("Unknown particle: %s", a_ParticleName.c_str());
ASSERT(!"Unknown particle");
return 0;
}
- return ParticleMap[ParticleName];
+ return FindResult->second;
}
@@ -1883,7 +1826,7 @@ UInt32 cProtocol_1_8_0::GetProtocolMobType(eMonsterType a_MobType)
switch (a_MobType)
{
// Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong)
- case mtInvalidType: return 52;
+ case mtInvalidType: return 53;
case mtBat: return 65;
case mtBlaze: return 61;
case mtCaveSpider: return 59;
@@ -1925,41 +1868,6 @@ UInt32 cProtocol_1_8_0::GetProtocolMobType(eMonsterType a_MobType)
-void cProtocol_1_8_0::FixItemFramePositions(int a_ObjectData, double & a_PosX, double & a_PosZ, double & a_Yaw)
-{
- switch (a_ObjectData)
- {
- case 0:
- {
- a_PosZ += 1;
- a_Yaw = 0;
- break;
- }
- case 1:
- {
- a_PosX -= 1;
- a_Yaw = 90;
- break;
- }
- case 2:
- {
- a_PosZ -= 1;
- a_Yaw = 180;
- break;
- }
- case 3:
- {
- a_PosX += 1;
- a_Yaw = 270;
- break;
- }
- }
-}
-
-
-
-
-
void cProtocol_1_8_0::AddReceivedData(const char * a_Data, size_t a_Size)
{
// Write the incoming data into the comm log file:
@@ -3918,3 +3826,76 @@ void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity &
a_Pkt.WriteBEInt32(0); // NumProperties
}
+
+
+
+
+
+void cProtocol_1_8_0::WriteEntitySpawn(cPacketizer & a_Pkt, const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData)
+{
+ ASSERT(m_State == 3); // In game mode?
+
+ a_Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ a_Pkt.WriteBEUInt8(a_ObjectType);
+ a_Pkt.WriteFPInt(a_Entity.GetPosX());
+ a_Pkt.WriteFPInt(a_Entity.GetPosY());
+ a_Pkt.WriteFPInt(a_Entity.GetPosY());
+ a_Pkt.WriteByteAngle(a_Entity.GetPitch());
+ a_Pkt.WriteByteAngle(a_Entity.GetYaw());
+ a_Pkt.WriteBEInt32(a_ObjectData);
+
+ if (a_ObjectData != 0)
+ {
+ a_Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400));
+ a_Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400));
+ a_Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400));
+ }
+}
+
+
+
+
+
+UInt8 cProtocol_1_8_0::GetProtocolEntityType(const cEntity & a_Entity)
+{
+ using Type = cEntity::eEntityType;
+
+ switch (a_Entity.GetEntityType())
+ {
+ case Type::etEnderCrystal: return 51;
+ case Type::etPickup: return 2;
+ case Type::etFallingBlock: return 70;
+ case Type::etMinecart: return 10;
+ case Type::etBoat: return 1;
+ case Type::etTNT: return 50;
+ case Type::etProjectile:
+ {
+ using PType = cProjectileEntity::eKind;
+ const auto & Projectile = static_cast<const cProjectileEntity &>(a_Entity);
+
+ switch (Projectile.GetProjectileKind())
+ {
+ case PType::pkArrow: return 60;
+ case PType::pkSnowball: return 61;
+ case PType::pkEgg: return 62;
+ case PType::pkGhastFireball: return 63;
+ case PType::pkFireCharge: return 64;
+ case PType::pkEnderPearl: return 65;
+ case PType::pkExpBottle: return 75;
+ case PType::pkSplashPotion: return 73;
+ case PType::pkFirework: return 76;
+ case PType::pkWitherSkull: return 66;
+ }
+ }
+ case Type::etFloater: return 90;
+ case Type::etItemFrame: return 71;
+ case Type::etLeashKnot: return 77;
+
+ // Non-objects must not be sent
+ case Type::etEntity:
+ case Type::etPlayer:
+ case Type::etMonster:
+ case Type::etExpOrb:
+ case Type::etPainting: UNREACHABLE("Tried to spawn an unhandled entity");
+ }
+}
diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h
index 7934b7038..69ac1449a 100644
--- a/src/Protocol/Protocol_1_8.h
+++ b/src/Protocol/Protocol_1_8.h
@@ -76,7 +76,6 @@ public:
virtual void SendLoginSuccess (void) override;
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
- virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
@@ -104,10 +103,8 @@ public:
virtual void SendSetTitle (const cCompositeChat & a_Title) override;
virtual void SendSetRawTitle (const AString & a_Title) override;
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
- virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
+ virtual void SendSpawnEntity (const cEntity & a_Entity) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
- virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData) override;
- virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override;
virtual void SendStatistics (const cStatManager & a_Manager) override;
virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
virtual void SendTeleportEntity (const cEntity & a_Entity) override;
@@ -135,9 +132,6 @@ public:
/** The 1.8 protocol use a particle id instead of a string. This function converts the name to the id. If the name is incorrect, it returns 0. */
static int GetParticleID(const AString & a_ParticleName);
- /** Minecraft 1.8 use other locations to spawn the item frame. This function converts the 1.7 positions to 1.8 positions. */
- static void FixItemFramePositions(int a_ObjectData, double & a_PosX, double & a_PosZ, double & a_Yaw);
-
protected:
AString m_ServerAddress;
@@ -167,7 +161,7 @@ protected:
virtual UInt32 GetPacketID(ePacketType a_Packet) override;
/** Converts eMonsterType to protocol-specific mob types */
- virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) override;
+ virtual UInt32 GetProtocolMobType(eMonsterType a_MobType);
/** Reads and handles the packet. The packet length and type have already been read.
Returns true if the packet was understood, false if it was an unknown packet
@@ -246,6 +240,15 @@ protected:
/** Writes the entity properties for the specified entity, including the Count field. */
virtual void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity);
+ /** Writes the entity type and entity-dependent data into a packet structure required for the entity to initially spawn. */
+ virtual void WriteEntitySpawn(cPacketizer & a_Pkt, const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData);
+
/** Writes the block entity data for the specified block entity into the packet. */
virtual void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity);
+
+private:
+
+ /** Converts an entity to a protocol-specific entity type.
+ Only entities that the Send Spawn Entity packet supports are valid inputs to this method */
+ UInt8 GetProtocolEntityType(const cEntity & a_Entity);
} ;
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 91bc43d03..10aed8cc1 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -329,35 +329,6 @@ void cProtocol_1_9_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_Da
-void cProtocol_1_9_0::SendPickupSpawn(const cPickup & a_Pickup)
-{
- ASSERT(m_State == 3); // In game mode?
-
- { // TODO Use SendSpawnObject
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_Pickup.GetUniqueID());
- // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
- Pkt.WriteBEUInt64(0);
- Pkt.WriteBEUInt64(a_Pickup.GetUniqueID());
- Pkt.WriteBEUInt8(2); // Type = Pickup
- Pkt.WriteBEDouble(a_Pickup.GetPosX());
- Pkt.WriteBEDouble(a_Pickup.GetPosY());
- Pkt.WriteBEDouble(a_Pickup.GetPosZ());
- Pkt.WriteByteAngle(a_Pickup.GetYaw());
- Pkt.WriteByteAngle(a_Pickup.GetPitch());
- Pkt.WriteBEInt32(0); // No object data
- Pkt.WriteBEInt16(0); // No velocity
- Pkt.WriteBEInt16(0);
- Pkt.WriteBEInt16(0);
- }
-
- SendEntityMetadata(a_Pickup);
-}
-
-
-
-
-
void cProtocol_1_9_0::SendPlayerMaxSpeed(void)
{
ASSERT(m_State == 3); // In game mode?
@@ -447,32 +418,6 @@ void cProtocol_1_9_0::SendSoundEffect(const AString & a_SoundName, double a_X, d
-void cProtocol_1_9_0::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_FallingBlock.GetUniqueID());
- // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
- Pkt.WriteBEUInt64(0);
- Pkt.WriteBEUInt64(a_FallingBlock.GetUniqueID());
- Pkt.WriteBEUInt8(70); // Falling block
- Vector3d LastSentPos = a_FallingBlock.GetLastSentPos();
- Pkt.WriteBEDouble(LastSentPos.x);
- Pkt.WriteBEDouble(LastSentPos.y);
- Pkt.WriteBEDouble(LastSentPos.z);
- Pkt.WriteByteAngle(a_FallingBlock.GetYaw());
- Pkt.WriteByteAngle(a_FallingBlock.GetPitch());
- Pkt.WriteBEInt32(static_cast<Int32>(a_FallingBlock.GetBlockType()) | (static_cast<Int32>(a_FallingBlock.GetBlockMeta()) << 12));
- Pkt.WriteBEInt16(static_cast<Int16>(a_FallingBlock.GetSpeedX() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_FallingBlock.GetSpeedY() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_FallingBlock.GetSpeedZ() * 400));
-}
-
-
-
-
-
void cProtocol_1_9_0::SendSpawnMob(const cMonster & a_Mob)
{
ASSERT(m_State == 3); // In game mode?
@@ -501,64 +446,6 @@ void cProtocol_1_9_0::SendSpawnMob(const cMonster & a_Mob)
-void cProtocol_1_9_0::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData)
-{
- ASSERT(m_State == 3); // In game mode?
- double PosX = a_Entity.GetPosX();
- double PosZ = a_Entity.GetPosZ();
- double Yaw = a_Entity.GetYaw();
- if (a_ObjectType == 71)
- {
- FixItemFramePositions(a_ObjectData, PosX, PosZ, Yaw);
- }
-
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
- Pkt.WriteBEUInt64(0);
- Pkt.WriteBEUInt64(a_Entity.GetUniqueID());
- Pkt.WriteBEUInt8(static_cast<UInt8>(a_ObjectType));
- Pkt.WriteBEDouble(PosX);
- Pkt.WriteBEDouble(a_Entity.GetPosY());
- Pkt.WriteBEDouble(PosZ);
- Pkt.WriteByteAngle(a_Entity.GetPitch());
- Pkt.WriteByteAngle(Yaw);
- Pkt.WriteBEInt32(a_ObjectData);
- Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400));
-}
-
-
-
-
-
-void cProtocol_1_9_0::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktSpawnObject);
- Pkt.WriteVarInt32(a_Vehicle.GetUniqueID());
- // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
- Pkt.WriteBEUInt64(0);
- Pkt.WriteBEUInt64(a_Vehicle.GetUniqueID());
- Pkt.WriteBEUInt8(static_cast<UInt8>(a_VehicleType));
- Vector3d LastSentPos = a_Vehicle.GetLastSentPos();
- Pkt.WriteBEDouble(LastSentPos.x);
- Pkt.WriteBEDouble(LastSentPos.y);
- Pkt.WriteBEDouble(LastSentPos.z);
- Pkt.WriteByteAngle(a_Vehicle.GetPitch());
- Pkt.WriteByteAngle(a_Vehicle.GetYaw());
- Pkt.WriteBEInt32(a_VehicleSubType);
- Pkt.WriteBEInt16(static_cast<Int16>(a_Vehicle.GetSpeedX() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Vehicle.GetSpeedY() * 400));
- Pkt.WriteBEInt16(static_cast<Int16>(a_Vehicle.GetSpeedZ() * 400));
-}
-
-
-
-
-
void cProtocol_1_9_0::SendTeleportEntity(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
@@ -2286,6 +2173,32 @@ void cProtocol_1_9_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity &
+void cProtocol_1_9_0::WriteEntitySpawn(cPacketizer & a_Pkt, const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData)
+{
+ ASSERT(m_State == 3); // In game mode?
+
+ a_Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+
+ // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now.
+ a_Pkt.WriteBEUInt64(0);
+ a_Pkt.WriteBEUInt64(a_Entity.GetUniqueID());
+
+ a_Pkt.WriteBEUInt8(a_ObjectType);
+ a_Pkt.WriteBEDouble(a_Entity.GetPosX());
+ a_Pkt.WriteBEDouble(a_Entity.GetPosY());
+ a_Pkt.WriteBEDouble(a_Entity.GetPosZ());
+ a_Pkt.WriteByteAngle(a_Entity.GetPitch());
+ a_Pkt.WriteByteAngle(a_Entity.GetYaw());
+ a_Pkt.WriteBEInt32(a_ObjectData);
+ a_Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedX() * 400));
+ a_Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedY() * 400));
+ a_Pkt.WriteBEInt16(static_cast<Int16>(a_Entity.GetSpeedZ() * 400));
+}
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cProtocol_1_9_1:
diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h
index d5b5d1f5a..b4e945c1e 100644
--- a/src/Protocol/Protocol_1_9.h
+++ b/src/Protocol/Protocol_1_9.h
@@ -54,15 +54,11 @@ public:
virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override;
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
- virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerMaxSpeed (void) override;
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
- virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
- virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData) override;
- virtual void SendSpawnVehicle (const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) override;
virtual void SendTeleportEntity (const cEntity & a_Entity) override;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendUnleashEntity (const cEntity & a_Entity) override;
@@ -127,6 +123,9 @@ protected:
/** Writes the entity properties for the specified entity, including the Count field. */
virtual void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) override;
+ /** Writes the entity type and entity-dependent data into a packet structure required for the entity to initially spawn. */
+ virtual void WriteEntitySpawn(cPacketizer & a_Pkt, const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) override;
+
/** Writes the block entity data for the specified block entity into the packet. */
virtual void WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity & a_BlockEntity) override;