mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-08 11:57:39 +08:00
Protocol: Use correct calculation for delta movements (#5455)
* Protocol: Use correct calculation for delta movements
This commit is contained in:
parent
5907df6808
commit
7a73fd467c
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
} ;
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user