summaryrefslogtreecommitdiffstats
path: root/src/Protocol
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Protocol/Protocol.h8
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp52
-rw-r--r--src/Protocol/ProtocolRecognizer.h8
-rw-r--r--src/Protocol/Protocol_1_11.cpp8
-rw-r--r--src/Protocol/Protocol_1_11.h2
-rw-r--r--src/Protocol/Protocol_1_8.cpp173
-rw-r--r--src/Protocol/Protocol_1_8.h19
-rw-r--r--src/Protocol/Protocol_1_9.cpp128
-rw-r--r--src/Protocol/Protocol_1_9.h10
9 files changed, 200 insertions, 208 deletions
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index fc1a1d9d3..12382b954 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -158,19 +158,19 @@ public:
virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) = 0;
virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) = 0;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0;
- virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player, int a_Count) = 0;
+ virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) = 0;
virtual void SendDestroyEntity (const cEntity & a_Entity) = 0;
virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) = 0;
virtual void SendDisconnect (const AString & a_Reason) = 0;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+)
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) = 0;
+ virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0;
virtual void SendEntityLook (const cEntity & a_Entity) = 0;
virtual void SendEntityMetadata (const cEntity & a_Entity) = 0;
+ virtual void SendEntityPosition (const cEntity & a_Entity) = 0;
virtual void SendEntityProperties (const cEntity & a_Entity) = 0;
- virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0;
- virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0;
virtual void SendEntityVelocity (const cEntity & a_Entity) = 0;
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0;
@@ -186,7 +186,6 @@ public:
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) = 0;
virtual void SendPaintingSpawn (const cPainting & a_Painting) = 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;
virtual void SendParticleEffect (const AString & a_SoundName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) = 0;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) = 0;
@@ -218,7 +217,6 @@ public:
virtual void SendSpawnMob (const cMonster & a_Mob) = 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;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) = 0;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index d5f40b19b..ddc1aaf93 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -233,10 +233,10 @@ void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSe
-void cProtocolRecognizer::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count)
+void cProtocolRecognizer::SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count)
{
ASSERT(m_Protocol != nullptr);
- m_Protocol->SendCollectEntity(a_Entity, a_Player, a_Count);
+ m_Protocol->SendCollectEntity(a_Collected, a_Collector, a_Count);
}
@@ -291,6 +291,16 @@ void cProtocolRecognizer::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cProtocolRecognizer::SendEntityAnimation(const cEntity & a_Entity, char a_Animation)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendEntityAnimation(a_Entity, a_Animation);
+}
+
+
+
+
+
void cProtocolRecognizer::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration)
{
ASSERT(m_Protocol != nullptr);
@@ -341,30 +351,20 @@ void cProtocolRecognizer::SendEntityMetadata(const cEntity & a_Entity)
-void cProtocolRecognizer::SendEntityProperties(const cEntity & a_Entity)
-{
- ASSERT(m_Protocol != nullptr);
- m_Protocol->SendEntityProperties(a_Entity);
-}
-
-
-
-
-
-void cProtocolRecognizer::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
+void cProtocolRecognizer::SendEntityPosition(const cEntity & a_Entity)
{
ASSERT(m_Protocol != nullptr);
- m_Protocol->SendEntityRelMove(a_Entity, a_RelX, a_RelY, a_RelZ);
+ m_Protocol->SendEntityPosition(a_Entity);
}
-void cProtocolRecognizer::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
+void cProtocolRecognizer::SendEntityProperties(const cEntity & a_Entity)
{
ASSERT(m_Protocol != nullptr);
- m_Protocol->SendEntityRelMoveLook(a_Entity, a_RelX, a_RelY, a_RelZ);
+ m_Protocol->SendEntityProperties(a_Entity);
}
@@ -560,16 +560,6 @@ void cProtocolRecognizer::SendPlayerAbilities(void)
-void cProtocolRecognizer::SendEntityAnimation(const cEntity & a_Entity, char a_Animation)
-{
- ASSERT(m_Protocol != nullptr);
- m_Protocol->SendEntityAnimation(a_Entity, a_Animation);
-}
-
-
-
-
-
void cProtocolRecognizer::SendPlayerListAddPlayer(const cPlayer & a_Player)
{
ASSERT(m_Protocol != nullptr);
@@ -860,16 +850,6 @@ void cProtocolRecognizer::SendTabCompletionResults(const AStringVector & a_Resul
-void cProtocolRecognizer::SendTeleportEntity(const cEntity & a_Entity)
-{
- ASSERT(m_Protocol != nullptr);
- m_Protocol->SendTeleportEntity(a_Entity);
-}
-
-
-
-
-
void cProtocolRecognizer::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
{
ASSERT(m_Protocol != nullptr);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index a658a95d9..f82dab08a 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -60,19 +60,19 @@ public:
virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) override;
virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player, int a_Count) override;
+ virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override;
virtual void SendDisconnect (const AString & a_Reason) override;
+ virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
virtual void SendEntityLook (const cEntity & a_Entity) override;
virtual void SendEntityMetadata (const cEntity & a_Entity) override;
+ virtual void SendEntityPosition (const cEntity & a_Entity) override;
virtual void SendEntityProperties (const cEntity & a_Entity) override;
- virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
- virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendEntityVelocity (const cEntity & a_Entity) override;
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override;
@@ -90,7 +90,6 @@ public:
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 SendPlayerAbilities (void) override;
- virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override;
virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override;
virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override;
@@ -120,7 +119,6 @@ public:
virtual void SendSpawnMob (const cMonster & a_Mob) 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;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index 3ccb76d39..677662a6f 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -341,13 +341,13 @@ cProtocol_1_11_0::cProtocol_1_11_0(cClientHandle * a_Client, const AString & a_S
-void cProtocol_1_11_0::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count)
+void cProtocol_1_11_0::SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktCollectEntity);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteVarInt32(a_Player.GetUniqueID());
+ Pkt.WriteVarInt32(a_Collected.GetUniqueID());
+ Pkt.WriteVarInt32(a_Collector.GetUniqueID());
Pkt.WriteVarInt32(static_cast<UInt32>(a_Count));
}
@@ -389,7 +389,7 @@ void cProtocol_1_11_0::SendSpawnMob(const cMonster & a_Mob)
Pkt.WriteBEUInt64(0);
Pkt.WriteBEUInt64(a_Mob.GetUniqueID());
Pkt.WriteVarInt32(GetProtocolMobType(a_Mob.GetMobType()));
- Vector3d LastSentPos = a_Mob.GetLastSentPos();
+ Vector3d LastSentPos = a_Mob.GetLastSentPosition();
Pkt.WriteBEDouble(LastSentPos.x);
Pkt.WriteBEDouble(LastSentPos.y);
Pkt.WriteBEDouble(LastSentPos.z);
diff --git a/src/Protocol/Protocol_1_11.h b/src/Protocol/Protocol_1_11.h
index b5c0bbeb8..a4d763d47 100644
--- a/src/Protocol/Protocol_1_11.h
+++ b/src/Protocol/Protocol_1_11.h
@@ -30,7 +30,7 @@ public:
cProtocol_1_11_0(cClientHandle * a_Client, const AString &a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State);
- virtual void SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count) override;
+ virtual void SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override;
virtual void SendHideTitle (void) override;
virtual void SendResetTitle (void) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index a2ea4eceb..4aa312fef 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -352,14 +352,14 @@ void cProtocol_1_8_0::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerial
-void cProtocol_1_8_0::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count)
+void cProtocol_1_8_0::SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count)
{
UNUSED(a_Count);
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, pktCollectEntity);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteVarInt32(a_Player.GetUniqueID());
+ Pkt.WriteVarInt32(a_Collected.GetUniqueID());
+ Pkt.WriteVarInt32(a_Collector.GetUniqueID());
}
@@ -430,6 +430,19 @@ void cProtocol_1_8_0::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cProtocol_1_8_0::SendEntityAnimation(const cEntity & a_Entity, char a_Animation)
+{
+ ASSERT(m_State == 3); // In game mode?
+
+ cPacketizer Pkt(*this, pktEntityAnimation);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEInt8(a_Animation);
+}
+
+
+
+
+
void cProtocol_1_8_0::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration)
{
ASSERT(m_State == 3); // In game mode?
@@ -502,47 +515,59 @@ void cProtocol_1_8_0::SendEntityMetadata(const cEntity & a_Entity)
-void cProtocol_1_8_0::SendEntityProperties(const cEntity & a_Entity)
+void cProtocol_1_8_0::SendEntityPosition(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
- cPacketizer Pkt(*this, pktEntityProperties);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- WriteEntityProperties(Pkt, a_Entity);
-}
-
+ const auto Delta = (a_Entity.GetPosition() - a_Entity.GetLastSentPosition()) * 32;
+ // Limitations of a byte
+ static const auto Max = std::numeric_limits<Int8>::max();
+ if ((std::abs(Delta.x) <= Max) && (std::abs(Delta.y) <= Max) && (std::abs(Delta.z) <= Max))
+ {
+ const auto Move = static_cast<Vector3<Int8>>(Delta);
+ // Difference within limitations, use a relative move packet
+ if (a_Entity.IsOrientationDirty())
+ {
+ cPacketizer Pkt(*this, pktEntityRelMoveLook);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEInt8(Move.x);
+ Pkt.WriteBEInt8(Move.y);
+ Pkt.WriteBEInt8(Move.z);
+ Pkt.WriteByteAngle(a_Entity.GetYaw());
+ Pkt.WriteByteAngle(a_Entity.GetPitch());
+ Pkt.WriteBool(a_Entity.IsOnGround());
+ }
+ else
+ {
+ cPacketizer Pkt(*this, pktEntityRelMove);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEInt8(Move.x);
+ Pkt.WriteBEInt8(Move.y);
+ Pkt.WriteBEInt8(Move.z);
+ Pkt.WriteBool(a_Entity.IsOnGround());
+ }
-void cProtocol_1_8_0::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
-{
- ASSERT(m_State == 3); // In game mode?
+ return;
+ }
- cPacketizer Pkt(*this, pktEntityRelMove);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEInt8(a_RelX);
- Pkt.WriteBEInt8(a_RelY);
- Pkt.WriteBEInt8(a_RelZ);
- Pkt.WriteBool(a_Entity.IsOnGround());
+ // Too big a movement, do a teleport
+ SendEntityTeleport(a_Entity);
}
-void cProtocol_1_8_0::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
+void cProtocol_1_8_0::SendEntityProperties(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
- cPacketizer Pkt(*this, pktEntityRelMoveLook);
+ cPacketizer Pkt(*this, pktEntityProperties);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEInt8(a_RelX);
- Pkt.WriteBEInt8(a_RelY);
- Pkt.WriteBEInt8(a_RelZ);
- Pkt.WriteByteAngle(a_Entity.GetYaw());
- Pkt.WriteByteAngle(a_Entity.GetPitch());
- Pkt.WriteBool(a_Entity.IsOnGround());
+ WriteEntityProperties(Pkt, a_Entity);
}
@@ -882,19 +907,6 @@ void cProtocol_1_8_0::SendPlayerAbilities(void)
-void cProtocol_1_8_0::SendEntityAnimation(const cEntity & a_Entity, char a_Animation)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktEntityAnimation);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEInt8(a_Animation);
-}
-
-
-
-
-
void cProtocol_1_8_0::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)
{
ASSERT(m_State == 3); // In game mode?
@@ -1133,7 +1145,7 @@ void cProtocol_1_8_0::SendPlayerSpawn(const cPlayer & a_Player)
cPacketizer Pkt(*this, pktSpawnOtherPlayer);
Pkt.WriteVarInt32(a_Player.GetUniqueID());
Pkt.WriteUUID(a_Player.GetUUID());
- Vector3d LastSentPos = a_Player.GetLastSentPos();
+ Vector3d LastSentPos = a_Player.GetLastSentPosition();
Pkt.WriteFPInt(LastSentPos.x);
Pkt.WriteFPInt(LastSentPos.y + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on.
Pkt.WriteFPInt(LastSentPos.z);
@@ -1386,8 +1398,7 @@ void cProtocol_1_8_0::SendSpawnEntity(const cEntity & a_Entity)
}
}
- cPacketizer Pkt(*this, pktSpawnObject);
- WriteEntitySpawn(Pkt, a_Entity, EntityType, EntityData);
+ SendEntitySpawn(a_Entity, EntityType, EntityData);
}
@@ -1401,7 +1412,7 @@ void cProtocol_1_8_0::SendSpawnMob(const cMonster & a_Mob)
cPacketizer Pkt(*this, pktSpawnMob);
Pkt.WriteVarInt32(a_Mob.GetUniqueID());
Pkt.WriteBEUInt8(static_cast<Byte>(GetProtocolMobType(a_Mob.GetMobType())));
- Vector3d LastSentPos = a_Mob.GetLastSentPos();
+ Vector3d LastSentPos = a_Mob.GetLastSentPosition();
Pkt.WriteFPInt(LastSentPos.x);
Pkt.WriteFPInt(LastSentPos.y);
Pkt.WriteFPInt(LastSentPos.z);
@@ -1458,24 +1469,6 @@ void cProtocol_1_8_0::SendTabCompletionResults(const AStringVector & a_Results)
-void cProtocol_1_8_0::SendTeleportEntity(const cEntity & a_Entity)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktTeleportEntity);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteFPInt(a_Entity.GetPosX());
- Pkt.WriteFPInt(a_Entity.GetPosY());
- Pkt.WriteFPInt(a_Entity.GetPosZ());
- Pkt.WriteByteAngle(a_Entity.GetYaw());
- Pkt.WriteByteAngle(a_Entity.GetPitch());
- Pkt.WriteBool(a_Entity.IsOnGround());
-}
-
-
-
-
-
void cProtocol_1_8_0::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
{
ASSERT(m_State == 3); // In game mode?
@@ -3201,6 +3194,37 @@ void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt)
+void cProtocol_1_8_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData)
+{
+ ASSERT(m_State == 3); // In game mode?
+
+ {
+ cPacketizer Pkt(*this, pktSpawnObject);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEUInt8(a_ObjectType);
+ Pkt.WriteFPInt(a_Entity.GetPosX()); // Position appears to be ignored...
+ Pkt.WriteFPInt(a_Entity.GetPosY());
+ Pkt.WriteFPInt(a_Entity.GetPosY());
+ Pkt.WriteByteAngle(a_Entity.GetPitch());
+ Pkt.WriteByteAngle(a_Entity.GetYaw());
+ 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));
+ }
+ }
+
+ // Otherwise 1.8 clients don't show the entity
+ SendEntityTeleport(a_Entity);
+}
+
+
+
+
+
void cProtocol_1_8_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
{
short ItemType = a_Item.m_ItemType;
@@ -3831,25 +3855,16 @@ void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity &
-void cProtocol_1_8_0::WriteEntitySpawn(cPacketizer & a_Pkt, const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData)
+void cProtocol_1_8_0::SendEntityTeleport(const cEntity & a_Entity)
{
- 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));
- }
+ cPacketizer Pkt(*this, pktTeleportEntity);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteFPInt(a_Entity.GetPosX());
+ Pkt.WriteFPInt(a_Entity.GetPosY());
+ Pkt.WriteFPInt(a_Entity.GetPosZ());
+ Pkt.WriteByteAngle(a_Entity.GetYaw());
+ Pkt.WriteByteAngle(a_Entity.GetPitch());
+ Pkt.WriteBool(a_Entity.IsOnGround());
}
diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h
index 69ac1449a..42903a921 100644
--- a/src/Protocol/Protocol_1_8.h
+++ b/src/Protocol/Protocol_1_8.h
@@ -47,19 +47,19 @@ public:
virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) override;
virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player, int a_Count) override;
+ virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
virtual void SendEntityLook (const cEntity & a_Entity) override;
virtual void SendEntityMetadata (const cEntity & a_Entity) override;
+ virtual void SendEntityPosition (const cEntity & a_Entity) override;
virtual void SendEntityProperties (const cEntity & a_Entity) override;
- virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
- virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendEntityVelocity (const cEntity & a_Entity) override;
virtual void SendExperience (void) override;
@@ -77,7 +77,6 @@ public:
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) 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;
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 SendPlayerListAddPlayer (const cPlayer & a_Player) override;
@@ -107,7 +106,6 @@ public:
virtual void SendSpawnMob (const cMonster & a_Mob) 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;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
@@ -228,6 +226,9 @@ protected:
If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */
eBlockFace FaceIntToBlockFace(Int8 a_FaceInt);
+ /** Sends the entity type and entity-dependent data required for the entity to initially spawn. */
+ virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData);
+
/** Writes the item data into a packet. */
virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item);
@@ -240,14 +241,16 @@ 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:
+ /** Sends an entity teleport packet.
+ Mitigates a 1.8 bug where the position in the entity spawn packet is ignored,
+ and so entities don't show up until a teleport is sent. */
+ void SendEntityTeleport(const cEntity & a_Entity);
+
/** 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 10aed8cc1..150e81339 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -170,33 +170,50 @@ void cProtocol_1_9_0::SendEntityMetadata(const cEntity & a_Entity)
-void cProtocol_1_9_0::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
+void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
- cPacketizer Pkt(*this, pktEntityRelMove);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- // TODO: 1.9 changed these from chars to shorts, meaning that there can be more percision and data. Other code needs to be updated for that.
- Pkt.WriteBEInt16(a_RelX * 128);
- Pkt.WriteBEInt16(a_RelY * 128);
- Pkt.WriteBEInt16(a_RelZ * 128);
- Pkt.WriteBool(a_Entity.IsOnGround());
-}
-
+ const auto Delta = (a_Entity.GetPosition() - a_Entity.GetLastSentPosition()) * 32 * 128;
+ // Limitations of a short
+ static const auto Max = std::numeric_limits<Int16>::max();
+ if ((std::abs(Delta.x) <= Max) && (std::abs(Delta.y) <= Max) && (std::abs(Delta.z) <= Max))
+ {
+ const auto Move = static_cast<Vector3<Int16>>(Delta);
+ // Difference within limitations, use a relative move packet
+ if (a_Entity.IsOrientationDirty())
+ {
+ cPacketizer Pkt(*this, pktEntityRelMoveLook);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEInt16(Move.x);
+ Pkt.WriteBEInt16(Move.y);
+ Pkt.WriteBEInt16(Move.z);
+ Pkt.WriteByteAngle(a_Entity.GetYaw());
+ Pkt.WriteByteAngle(a_Entity.GetPitch());
+ Pkt.WriteBool(a_Entity.IsOnGround());
+ }
+ else
+ {
+ cPacketizer Pkt(*this, pktEntityRelMove);
+ Pkt.WriteVarInt32(a_Entity.GetUniqueID());
+ Pkt.WriteBEInt16(Move.x);
+ Pkt.WriteBEInt16(Move.y);
+ Pkt.WriteBEInt16(Move.z);
+ Pkt.WriteBool(a_Entity.IsOnGround());
+ }
-void cProtocol_1_9_0::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
-{
- ASSERT(m_State == 3); // In game mode?
+ return;
+ }
- cPacketizer Pkt(*this, pktEntityRelMoveLook);
+ // Too big a movement, do a teleport
+ cPacketizer Pkt(*this, pktTeleportEntity);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- // TODO: 1.9 changed these from chars to shorts, meaning that there can be more percision and data. Other code needs to be updated for that.
- Pkt.WriteBEInt16(a_RelX * 128);
- Pkt.WriteBEInt16(a_RelY * 128);
- Pkt.WriteBEInt16(a_RelZ * 128);
+ Pkt.WriteBEDouble(a_Entity.GetPosX());
+ Pkt.WriteBEDouble(a_Entity.GetPosY());
+ Pkt.WriteBEDouble(a_Entity.GetPosZ());
Pkt.WriteByteAngle(a_Entity.GetYaw());
Pkt.WriteByteAngle(a_Entity.GetPitch());
Pkt.WriteBool(a_Entity.IsOnGround());
@@ -386,7 +403,7 @@ void cProtocol_1_9_0::SendPlayerSpawn(const cPlayer & a_Player)
cPacketizer Pkt(*this, pktSpawnOtherPlayer);
Pkt.WriteVarInt32(a_Player.GetUniqueID());
Pkt.WriteUUID(a_Player.GetUUID());
- Vector3d LastSentPos = a_Player.GetLastSentPos();
+ Vector3d LastSentPos = a_Player.GetLastSentPosition();
Pkt.WriteBEDouble(LastSentPos.x);
Pkt.WriteBEDouble(LastSentPos.y + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on.
Pkt.WriteBEDouble(LastSentPos.z);
@@ -428,7 +445,7 @@ void cProtocol_1_9_0::SendSpawnMob(const cMonster & a_Mob)
Pkt.WriteBEUInt64(0);
Pkt.WriteBEUInt64(a_Mob.GetUniqueID());
Pkt.WriteBEUInt8(static_cast<Byte>(GetProtocolMobType(a_Mob.GetMobType())));
- Vector3d LastSentPos = a_Mob.GetLastSentPos();
+ Vector3d LastSentPos = a_Mob.GetLastSentPosition();
Pkt.WriteBEDouble(LastSentPos.x);
Pkt.WriteBEDouble(LastSentPos.y);
Pkt.WriteBEDouble(LastSentPos.z);
@@ -446,24 +463,6 @@ void cProtocol_1_9_0::SendSpawnMob(const cMonster & a_Mob)
-void cProtocol_1_9_0::SendTeleportEntity(const cEntity & a_Entity)
-{
- ASSERT(m_State == 3); // In game mode?
-
- cPacketizer Pkt(*this, pktTeleportEntity);
- Pkt.WriteVarInt32(a_Entity.GetUniqueID());
- Pkt.WriteBEDouble(a_Entity.GetPosX());
- Pkt.WriteBEDouble(a_Entity.GetPosY());
- Pkt.WriteBEDouble(a_Entity.GetPosZ());
- Pkt.WriteByteAngle(a_Entity.GetYaw());
- Pkt.WriteByteAngle(a_Entity.GetPitch());
- Pkt.WriteBool(a_Entity.IsOnGround());
-}
-
-
-
-
-
void cProtocol_1_9_0::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
{
ASSERT(m_State == 3); // In game mode?
@@ -1323,6 +1322,33 @@ eHand cProtocol_1_9_0::HandIntToEnum(Int32 a_Hand)
+void cProtocol_1_9_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData)
+{
+ ASSERT(m_State == 3); // In game mode?
+
+ 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(a_ObjectType);
+ Pkt.WriteBEDouble(a_Entity.GetPosX());
+ Pkt.WriteBEDouble(a_Entity.GetPosY());
+ Pkt.WriteBEDouble(a_Entity.GetPosZ());
+ Pkt.WriteByteAngle(a_Entity.GetPitch());
+ Pkt.WriteByteAngle(a_Entity.GetYaw());
+ 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::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
{
short ItemType = a_Item.m_ItemType;
@@ -2173,32 +2199,6 @@ 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 b4e945c1e..75fff9020 100644
--- a/src/Protocol/Protocol_1_9.h
+++ b/src/Protocol/Protocol_1_9.h
@@ -46,8 +46,7 @@ public:
virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityMetadata (const cEntity & a_Entity) override;
- virtual void SendEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
- virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
+ virtual void SendEntityPosition (const cEntity & a_Entity) override;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendKeepAlive (UInt32 a_PingID) override;
@@ -59,7 +58,6 @@ public:
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 SendSpawnMob (const cMonster & a_Mob) 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;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
@@ -111,6 +109,9 @@ protected:
If the received value doesn't match any of the know value, raise an assertion fail or return hMain. */
eHand HandIntToEnum(Int32 a_Hand);
+ /** Sends the entity type and entity-dependent data required for the entity to initially spawn. */
+ virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) override;
+
/** Writes the item data into a packet. */
virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) override;
@@ -123,9 +124,6 @@ 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;