summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ByteBuffer.cpp18
-rw-r--r--src/ByteBuffer.h9
-rw-r--r--src/Entities/Entity.cpp5
-rw-r--r--src/Protocol/Protocol_1_8.cpp41
-rw-r--r--src/Protocol/Protocol_1_8.h5
-rw-r--r--src/Protocol/Protocol_1_9.cpp16
6 files changed, 56 insertions, 38 deletions
diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp
index 46f2ba0d4..8121fc3ef 100644
--- a/src/ByteBuffer.cpp
+++ b/src/ByteBuffer.cpp
@@ -214,6 +214,24 @@ size_t cByteBuffer::GetReadableSpace(void) const
+bool cByteBuffer::CanBEInt8Represent(int a_Value)
+{
+ return (-128 <= a_Value) && (a_Value <= 127);
+}
+
+
+
+
+
+bool cByteBuffer::CanBEInt16Represent(int a_Value)
+{
+ return (-32768 <= a_Value) && (a_Value <= 32767);
+}
+
+
+
+
+
bool cByteBuffer::CanReadBytes(size_t a_Count) const
{
CHECK_THREAD
diff --git a/src/ByteBuffer.h b/src/ByteBuffer.h
index 1d108fca2..664887132 100644
--- a/src/ByteBuffer.h
+++ b/src/ByteBuffer.h
@@ -31,6 +31,7 @@ their own synchronization.
class cByteBuffer
{
public:
+
cByteBuffer(size_t a_BufferSize);
~cByteBuffer();
@@ -47,7 +48,13 @@ public:
size_t GetReadableSpace(void) const;
/** Returns the current data start index. For debugging purposes. */
- size_t GetDataStart(void) const { return m_DataStart; }
+ size_t GetDataStart(void) const { return m_DataStart; }
+
+ /** Returns if the given value can fit in a protocol big-endian 8 bit integer. */
+ static bool CanBEInt8Represent(int a_Value);
+
+ /** Returns if the given value can fit in a protocol big-endian 16 bit integer. */
+ static bool CanBEInt16Represent(int a_Value);
/** Returns true if the specified amount of bytes are available for reading */
bool CanReadBytes(size_t a_Count) const;
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 0718da06c..c46f9e644 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1970,7 +1970,7 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
return;
}
- if (GetSpeed().SqrLength() > 0.001)
+ if (m_Speed.HasNonZeroLength())
{
// Movin'
m_World->BroadcastEntityVelocity(*this, a_Exclude);
@@ -1986,8 +1986,7 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
m_bHasSentNoSpeed = true;
}
- Vector3i Diff = (GetPosition() * 32.0).Floor() - (m_LastSentPosition * 32.0).Floor();
- if (Diff.HasNonZeroLength()) // Have we moved?
+ if ((m_Position - m_LastSentPosition).HasNonZeroLength()) // Have we moved?
{
m_World->BroadcastEntityPosition(*this, a_Exclude);
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index e949d6116..d56375a8d 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -579,12 +579,15 @@ void cProtocol_1_8_0::SendEntityPosition(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
- const auto Delta = (a_Entity.GetPosition() - a_Entity.GetLastSentPosition()) * 32;
+ const auto Delta = (a_Entity.GetPosition() * 32).Floor() - (a_Entity.GetLastSentPosition() * 32).Floor();
- // 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))
+ // Ensure that the delta has enough precision and is within range of a BEInt8:
+ if (
+ Delta.HasNonZeroLength() &&
+ cByteBuffer::CanBEInt8Represent(Delta.x) &&
+ cByteBuffer::CanBEInt8Represent(Delta.y) &&
+ cByteBuffer::CanBEInt8Represent(Delta.z)
+ )
{
const auto Move = static_cast<Vector3<Int8>>(Delta);
@@ -613,8 +616,16 @@ void cProtocol_1_8_0::SendEntityPosition(const cEntity & a_Entity)
return;
}
- // Too big a movement, do a teleport
- SendEntityTeleport(a_Entity);
+ // Too big or small a movement, do a teleport.
+
+ 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());
}
@@ -4202,22 +4213,6 @@ void cProtocol_1_8_0::HandlePacket(cByteBuffer & a_Buffer)
-void cProtocol_1_8_0::SendEntityTeleport(const cEntity & a_Entity)
-{
- 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::StartEncryption(const Byte * a_Key)
{
m_Encryptor.Init(a_Key, a_Key);
diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h
index eaa8813be..ed13399ef 100644
--- a/src/Protocol/Protocol_1_8.h
+++ b/src/Protocol/Protocol_1_8.h
@@ -270,10 +270,5 @@ private:
/** Handle a complete packet stored in the given buffer. */
void HandlePacket(cByteBuffer & a_Buffer);
- /** 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);
-
void StartEncryption(const Byte * a_Key);
} ;
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index dd2133f77..9a4bcdc4a 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -307,12 +307,15 @@ void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity)
{
ASSERT(m_State == 3); // In game mode?
- const auto Delta = (a_Entity.GetPosition() - a_Entity.GetLastSentPosition()) * 32 * 128;
+ const auto Delta = (a_Entity.GetPosition() * 32 * 128).Floor() - (a_Entity.GetLastSentPosition() * 32 * 128).Floor();
- // 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))
+ // Ensure that the delta has enough precision and is within range of a BEInt16:
+ if (
+ Delta.HasNonZeroLength() &&
+ cByteBuffer::CanBEInt16Represent(Delta.x) &&
+ cByteBuffer::CanBEInt16Represent(Delta.y) &&
+ cByteBuffer::CanBEInt16Represent(Delta.z)
+ )
{
const auto Move = static_cast<Vector3<Int16>>(Delta);
@@ -341,7 +344,8 @@ void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity)
return;
}
- // Too big a movement, do a teleport
+ // Too big or small a movement, do a teleport.
+
cPacketizer Pkt(*this, pktTeleportEntity);
Pkt.WriteVarInt32(a_Entity.GetUniqueID());
Pkt.WriteBEDouble(a_Entity.GetPosX());