Merge pull request #2379 from cuberite/hunger
Hopefully fixed food drain bugs
This commit is contained in:
commit
7cf741abde
@ -20,7 +20,6 @@
|
|||||||
#include "ChatColor.h"
|
#include "ChatColor.h"
|
||||||
#include "Items/ItemHandler.h"
|
#include "Items/ItemHandler.h"
|
||||||
#include "Blocks/BlockHandler.h"
|
#include "Blocks/BlockHandler.h"
|
||||||
#include "Blocks/BlockSlab.h"
|
|
||||||
#include "Blocks/BlockBed.h"
|
#include "Blocks/BlockBed.h"
|
||||||
#include "Blocks/ChunkInterface.h"
|
#include "Blocks/ChunkInterface.h"
|
||||||
#include "BlockInServerPluginInterface.h"
|
#include "BlockInServerPluginInterface.h"
|
||||||
@ -760,40 +759,31 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Vector3d NewPosition(a_PosX, a_PosY, a_PosZ);
|
||||||
// TODO: Invalid stance check
|
Vector3d OldPosition = GetPlayer()->GetPosition();
|
||||||
if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
|
auto PreviousIsOnGround = GetPlayer()->IsOnGround();
|
||||||
{
|
|
||||||
LOGD("Invalid stance");
|
|
||||||
SendPlayerMoveLook();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// If the player has moved too far, "repair" them:
|
// If the player has moved too far, "repair" them:
|
||||||
Vector3d Pos(a_PosX, a_PosY, a_PosZ);
|
if ((OldPosition - NewPosition).SqrLength() > 100 * 100)
|
||||||
if ((m_Player->GetPosition() - Pos).SqrLength() > 100 * 100)
|
|
||||||
{
|
{
|
||||||
LOGD("Too far away (%0.2f), \"repairing\" the client", (m_Player->GetPosition() - Pos).Length());
|
LOGD("Too far away (%0.2f), \"repairing\" the client", (OldPosition - NewPosition).Length());
|
||||||
SendPlayerMoveLook();
|
SendPlayerMoveLook();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a jump just started, process food exhaustion:
|
|
||||||
if ((a_PosY > m_Player->GetPosY()) && !a_IsOnGround && m_Player->IsOnGround())
|
|
||||||
{
|
|
||||||
// we only add this exhaustion if the player is not swimming - otherwise we end up with both jump + swim exhaustion
|
|
||||||
|
|
||||||
if (!m_Player->IsSwimming())
|
if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*m_Player, OldPosition, NewPosition))
|
||||||
{
|
{
|
||||||
m_Player->GetStatManager().AddValue(statJumps, 1);
|
SendPlayerMoveLook();
|
||||||
m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2);
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: should do some checks to see if player is not moving through terrain
|
||||||
|
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too
|
||||||
|
|
||||||
m_Player->MoveTo(Pos);
|
m_Player->SetPosition(NewPosition);
|
||||||
m_Player->SetStance(a_Stance);
|
m_Player->SetStance(a_Stance);
|
||||||
m_Player->SetTouchGround(a_IsOnGround);
|
m_Player->SetTouchGround(a_IsOnGround);
|
||||||
|
m_Player->UpdateMovementStats(NewPosition - OldPosition, PreviousIsOnGround);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1501,8 +1491,8 @@ void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsO
|
|||||||
|
|
||||||
void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround)
|
void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround)
|
||||||
{
|
{
|
||||||
HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround);
|
|
||||||
HandlePlayerPos(a_PosX, a_PosY, a_PosZ, a_Stance, a_IsOnGround);
|
HandlePlayerPos(a_PosX, a_PosY, a_PosZ, a_Stance, a_IsOnGround);
|
||||||
|
HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -321,7 +321,14 @@ public: // tolua_export
|
|||||||
void HandlePlayerAbilities (bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed);
|
void HandlePlayerAbilities (bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed);
|
||||||
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
|
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
|
||||||
void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay)
|
void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay)
|
||||||
void HandlePlayerPos (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround);
|
|
||||||
|
/** Verifies and sets player position, performing relevant checks
|
||||||
|
Calls relevant methods to process movement related statistics
|
||||||
|
Requires state of previous position and on-ground status, so must be called when these are still intact
|
||||||
|
*/
|
||||||
|
void HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround);
|
||||||
|
|
||||||
|
|
||||||
void HandlePluginMessage (const AString & a_Channel, const AString & a_Message);
|
void HandlePluginMessage (const AString & a_Channel, const AString & a_Message);
|
||||||
void HandleRespawn (void);
|
void HandleRespawn (void);
|
||||||
void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem);
|
void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem);
|
||||||
|
@ -15,7 +15,7 @@ class cColor
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum
|
enum : unsigned int
|
||||||
{
|
{
|
||||||
COLOR_MIN = 0,
|
COLOR_MIN = 0,
|
||||||
COLOR_MAX = 255,
|
COLOR_MAX = 255,
|
||||||
|
@ -38,7 +38,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
|||||||
m_bOnGround(false),
|
m_bOnGround(false),
|
||||||
m_Gravity(-9.81f),
|
m_Gravity(-9.81f),
|
||||||
m_AirDrag(0.02f),
|
m_AirDrag(0.02f),
|
||||||
m_LastPos(a_X, a_Y, a_Z),
|
m_LastPosition(a_X, a_Y, a_Z),
|
||||||
m_IsInitialized(false),
|
m_IsInitialized(false),
|
||||||
m_WorldTravellingFrom(nullptr),
|
m_WorldTravellingFrom(nullptr),
|
||||||
m_EntityType(a_EntityType),
|
m_EntityType(a_EntityType),
|
||||||
@ -57,7 +57,8 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
|||||||
m_TicksAlive(0),
|
m_TicksAlive(0),
|
||||||
m_HeadYaw(0.0),
|
m_HeadYaw(0.0),
|
||||||
m_Rot(0.0, 0.0, 0.0),
|
m_Rot(0.0, 0.0, 0.0),
|
||||||
m_Pos(a_X, a_Y, a_Z),
|
m_Position(a_X, a_Y, a_Z),
|
||||||
|
m_LastSentPosition(a_X, a_Y, a_Z),
|
||||||
m_WaterSpeed(0, 0, 0),
|
m_WaterSpeed(0, 0, 0),
|
||||||
m_Mass (0.001), // Default 1g
|
m_Mass (0.001), // Default 1g
|
||||||
m_Width(a_Width),
|
m_Width(a_Width),
|
||||||
@ -793,17 +794,7 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
if (m_AttachedTo != nullptr)
|
if (m_AttachedTo != nullptr)
|
||||||
{
|
{
|
||||||
Vector3d DeltaPos = m_Pos - m_AttachedTo->GetPosition();
|
SetPosition(m_AttachedTo->GetPosition());
|
||||||
if (DeltaPos.Length() > 0.5)
|
|
||||||
{
|
|
||||||
SetPosition(m_AttachedTo->GetPosition());
|
|
||||||
|
|
||||||
if (IsPlayer())
|
|
||||||
{
|
|
||||||
cPlayer * Player = reinterpret_cast<cPlayer *>(this);
|
|
||||||
Player->UpdateMovementStats(DeltaPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1692,7 +1683,7 @@ void cEntity::TeleportToEntity(cEntity & a_Entity)
|
|||||||
void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
||||||
{
|
{
|
||||||
// ask the plugins to allow teleport to the new position.
|
// ask the plugins to allow teleport to the new position.
|
||||||
if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPos, Vector3d(a_PosX, a_PosY, a_PosZ)))
|
if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ)))
|
||||||
{
|
{
|
||||||
SetPosition(a_PosX, a_PosY, a_PosZ);
|
SetPosition(a_PosX, a_PosY, a_PosZ);
|
||||||
m_World->BroadcastTeleportEntity(*this);
|
m_World->BroadcastTeleportEntity(*this);
|
||||||
@ -1727,9 +1718,9 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pickups move disgracefully if relative move packets are sent as opposed to just velocity. Have a system to send relmove only when SetPosXXX() is called with a large difference in position
|
// TODO: Pickups move disgracefully if relative move packets are sent as opposed to just velocity. Have a system to send relmove only when SetPosXXX() is called with a large difference in position
|
||||||
int DiffX = FloorC(GetPosX() * 32.0) - FloorC(m_LastPos.x * 32.0);
|
int DiffX = FloorC(GetPosX() * 32.0) - FloorC(m_LastSentPosition.x * 32.0);
|
||||||
int DiffY = FloorC(GetPosY() * 32.0) - FloorC(m_LastPos.y * 32.0);
|
int DiffY = FloorC(GetPosY() * 32.0) - FloorC(m_LastSentPosition.y * 32.0);
|
||||||
int DiffZ = FloorC(GetPosZ() * 32.0) - FloorC(m_LastPos.z * 32.0);
|
int DiffZ = FloorC(GetPosZ() * 32.0) - FloorC(m_LastSentPosition.z * 32.0);
|
||||||
|
|
||||||
if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved?
|
if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved?
|
||||||
{
|
{
|
||||||
@ -1746,14 +1737,14 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
|
|||||||
m_World->BroadcastEntityRelMove(*this, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ), a_Exclude);
|
m_World->BroadcastEntityRelMove(*this, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ), a_Exclude);
|
||||||
}
|
}
|
||||||
// Clients seem to store two positions, one for the velocity packet and one for the teleport / relmove packet
|
// Clients seem to store two positions, one for the velocity packet and one for the teleport / relmove packet
|
||||||
// The latter is only changed with a relmove / teleport, and m_LastPos stores this position
|
// The latter is only changed with a relmove / teleport, and m_LastSentPosition stores this position
|
||||||
m_LastPos = GetPosition();
|
m_LastSentPosition = GetPosition();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Too big a movement, do a teleport
|
// Too big a movement, do a teleport
|
||||||
m_World->BroadcastTeleportEntity(*this, a_Exclude);
|
m_World->BroadcastTeleportEntity(*this, a_Exclude);
|
||||||
m_LastPos = GetPosition(); // See above
|
m_LastSentPosition = GetPosition(); // See above
|
||||||
m_bDirtyOrientation = false;
|
m_bDirtyOrientation = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1824,16 +1815,6 @@ bool cEntity::IsA(const char * a_ClassName) const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::SetRot(const Vector3f & a_Rot)
|
|
||||||
{
|
|
||||||
m_Rot = a_Rot;
|
|
||||||
m_bDirtyOrientation = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::SetHeadYaw(double a_HeadYaw)
|
void cEntity::SetHeadYaw(double a_HeadYaw)
|
||||||
{
|
{
|
||||||
m_HeadYaw = a_HeadYaw;
|
m_HeadYaw = a_HeadYaw;
|
||||||
@ -1939,41 +1920,6 @@ void cEntity::SetWidth(double a_Width)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::AddPosX(double a_AddPosX)
|
|
||||||
{
|
|
||||||
m_Pos.x += a_AddPosX;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::AddPosY(double a_AddPosY)
|
|
||||||
{
|
|
||||||
m_Pos.y += a_AddPosY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::AddPosZ(double a_AddPosZ)
|
|
||||||
{
|
|
||||||
m_Pos.z += a_AddPosZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
|
|
||||||
{
|
|
||||||
m_Pos.x += a_AddPosX;
|
|
||||||
m_Pos.y += a_AddPosY;
|
|
||||||
m_Pos.z += a_AddPosZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ)
|
void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ)
|
||||||
{
|
{
|
||||||
DoSetSpeed(m_Speed.x + a_AddSpeedX, m_Speed.y + a_AddSpeedY, m_Speed.z + a_AddSpeedZ);
|
DoSetSpeed(m_Speed.x + a_AddSpeedX, m_Speed.y + a_AddSpeedY, m_Speed.z + a_AddSpeedZ);
|
||||||
@ -2055,36 +2001,10 @@ Vector3d cEntity::GetLookVector(void) const
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Set position
|
// Set position
|
||||||
void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
void cEntity::SetPosition(const Vector3d & a_Position)
|
||||||
{
|
{
|
||||||
m_Pos.Set(a_PosX, a_PosY, a_PosZ);
|
m_LastPosition = m_Position;
|
||||||
}
|
m_Position = a_Position;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::SetPosX(double a_PosX)
|
|
||||||
{
|
|
||||||
m_Pos.x = a_PosX;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::SetPosY(double a_PosY)
|
|
||||||
{
|
|
||||||
m_Pos.y = a_PosY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::SetPosZ(double a_PosZ)
|
|
||||||
{
|
|
||||||
m_Pos.z = a_PosZ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#define POSX_TOINT FloorC(GetPosX())
|
#define POSX_TOINT FloorC(GetPosX())
|
||||||
#define POSY_TOINT FloorC(GetPosY())
|
#define POSY_TOINT FloorC(GetPosY())
|
||||||
#define POSZ_TOINT FloorC(GetPosZ())
|
#define POSZ_TOINT FloorC(GetPosZ())
|
||||||
#define POS_TOINT Vector3i(POSXTOINT, POSYTOINT, POSZTOINT)
|
#define POS_TOINT GetPosition().Floor()
|
||||||
|
|
||||||
#define GET_AND_VERIFY_CURRENT_CHUNK(ChunkVarName, X, Z) cChunk * ChunkVarName = a_Chunk.GetNeighborChunk(X, Z); if ((ChunkVarName == nullptr) || !ChunkVarName->IsValid()) { return; }
|
#define GET_AND_VERIFY_CURRENT_CHUNK(ChunkVarName, X, Z) cChunk * ChunkVarName = a_Chunk.GetNeighborChunk(X, Z); if ((ChunkVarName == nullptr) || !ChunkVarName->IsValid()) { return; }
|
||||||
|
|
||||||
@ -190,11 +190,10 @@ public:
|
|||||||
double GetHeadYaw (void) const { return m_HeadYaw; } // In degrees
|
double GetHeadYaw (void) const { return m_HeadYaw; } // In degrees
|
||||||
double GetHeight (void) const { return m_Height; }
|
double GetHeight (void) const { return m_Height; }
|
||||||
double GetMass (void) const { return m_Mass; }
|
double GetMass (void) const { return m_Mass; }
|
||||||
const Vector3d & GetPosition (void) const { return m_Pos; }
|
const Vector3d & GetPosition (void) const { return m_Position; }
|
||||||
double GetPosX (void) const { return m_Pos.x; }
|
double GetPosX (void) const { return m_Position.x; }
|
||||||
double GetPosY (void) const { return m_Pos.y; }
|
double GetPosY (void) const { return m_Position.y; }
|
||||||
double GetPosZ (void) const { return m_Pos.z; }
|
double GetPosZ (void) const { return m_Position.z; }
|
||||||
const Vector3d & GetRot (void) const { return m_Rot; } // OBSOLETE, use individual GetYaw(), GetPitch, GetRoll() components
|
|
||||||
double GetYaw (void) const { return m_Rot.x; } // In degrees, [-180, +180)
|
double GetYaw (void) const { return m_Rot.x; } // In degrees, [-180, +180)
|
||||||
double GetPitch (void) const { return m_Rot.y; } // In degrees, [-180, +180), but normal client clips to [-90, +90]
|
double GetPitch (void) const { return m_Rot.y; } // In degrees, [-180, +180), but normal client clips to [-90, +90]
|
||||||
double GetRoll (void) const { return m_Rot.z; } // In degrees, unused in current client
|
double GetRoll (void) const { return m_Rot.z; } // In degrees, unused in current client
|
||||||
@ -205,18 +204,17 @@ public:
|
|||||||
double GetSpeedZ (void) const { return m_Speed.z; }
|
double GetSpeedZ (void) const { return m_Speed.z; }
|
||||||
double GetWidth (void) const { return m_Width; }
|
double GetWidth (void) const { return m_Width; }
|
||||||
|
|
||||||
int GetChunkX(void) const {return static_cast<int>(floor(m_Pos.x / cChunkDef::Width)); }
|
int GetChunkX(void) const { return FloorC(m_Position.x / cChunkDef::Width); }
|
||||||
int GetChunkZ(void) const {return static_cast<int>(floor(m_Pos.z / cChunkDef::Width)); }
|
int GetChunkZ(void) const { return FloorC(m_Position.z / cChunkDef::Width); }
|
||||||
|
|
||||||
void SetHeadYaw (double a_HeadYaw);
|
void SetHeadYaw (double a_HeadYaw);
|
||||||
void SetHeight (double a_Height);
|
void SetHeight (double a_Height);
|
||||||
void SetMass (double a_Mass);
|
void SetMass (double a_Mass);
|
||||||
void SetPosX (double a_PosX);
|
void SetPosX (double a_PosX) { SetPosition({a_PosX, m_Position.y, m_Position.z}); }
|
||||||
void SetPosY (double a_PosY);
|
void SetPosY (double a_PosY) { SetPosition({m_Position.x, a_PosY, m_Position.z}); }
|
||||||
void SetPosZ (double a_PosZ);
|
void SetPosZ (double a_PosZ) { SetPosition({m_Position.x, m_Position.y, a_PosZ}); }
|
||||||
void SetPosition(double a_PosX, double a_PosY, double a_PosZ);
|
void SetPosition(double a_PosX, double a_PosY, double a_PosZ) { SetPosition({a_PosX, a_PosY, a_PosZ}); }
|
||||||
void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x, a_Pos.y, a_Pos.z); }
|
void SetPosition(const Vector3d & a_Position);
|
||||||
void SetRot (const Vector3f & a_Rot); // OBSOLETE, use individual SetYaw(), SetPitch(), SetRoll() components
|
|
||||||
void SetYaw (double a_Yaw); // In degrees, normalizes to [-180, +180)
|
void SetYaw (double a_Yaw); // In degrees, normalizes to [-180, +180)
|
||||||
void SetPitch (double a_Pitch); // In degrees, normalizes to [-180, +180)
|
void SetPitch (double a_Pitch); // In degrees, normalizes to [-180, +180)
|
||||||
void SetRoll (double a_Roll); // In degrees, normalizes to [-180, +180)
|
void SetRoll (double a_Roll); // In degrees, normalizes to [-180, +180)
|
||||||
@ -238,10 +236,10 @@ public:
|
|||||||
|
|
||||||
void SetWidth (double a_Width);
|
void SetWidth (double a_Width);
|
||||||
|
|
||||||
void AddPosX (double a_AddPosX);
|
void AddPosX (double a_AddPosX) { AddPosition(a_AddPosX, 0, 0); }
|
||||||
void AddPosY (double a_AddPosY);
|
void AddPosY (double a_AddPosY) { AddPosition(0, a_AddPosY, 0); }
|
||||||
void AddPosZ (double a_AddPosZ);
|
void AddPosZ (double a_AddPosZ) { AddPosition(0, 0, a_AddPosZ); }
|
||||||
void AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ);
|
void AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ) { SetPosition(m_Position + Vector3d(a_AddPosX, a_AddPosY, a_AddPosZ)); }
|
||||||
void AddPosition(const Vector3d & a_AddPos) { AddPosition(a_AddPos.x, a_AddPos.y, a_AddPos.z); }
|
void AddPosition(const Vector3d & a_AddPos) { AddPosition(a_AddPos.x, a_AddPos.y, a_AddPos.z); }
|
||||||
void AddSpeed (double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ);
|
void AddSpeed (double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ);
|
||||||
void AddSpeed (const Vector3d & a_AddSpeed) { AddSpeed(a_AddSpeed.x, a_AddSpeed.y, a_AddSpeed.z); }
|
void AddSpeed (const Vector3d & a_AddSpeed) { AddSpeed(a_AddSpeed.x, a_AddSpeed.y, a_AddSpeed.z); }
|
||||||
@ -531,9 +529,7 @@ protected:
|
|||||||
Data: http://minecraft.gamepedia.com/Entity#Motion_of_entities */
|
Data: http://minecraft.gamepedia.com/Entity#Motion_of_entities */
|
||||||
float m_AirDrag;
|
float m_AirDrag;
|
||||||
|
|
||||||
/** Last position sent to client via the Relative Move or Teleport packets (not Velocity)
|
Vector3d m_LastPosition;
|
||||||
Only updated if cEntity::BroadcastMovementUpdate() is called! */
|
|
||||||
Vector3d m_LastPos;
|
|
||||||
|
|
||||||
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
|
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
|
||||||
bool m_IsInitialized;
|
bool m_IsInitialized;
|
||||||
@ -610,7 +606,11 @@ private:
|
|||||||
Vector3d m_Rot;
|
Vector3d m_Rot;
|
||||||
|
|
||||||
/** Position of the entity's XZ center and Y bottom */
|
/** Position of the entity's XZ center and Y bottom */
|
||||||
Vector3d m_Pos;
|
Vector3d m_Position;
|
||||||
|
|
||||||
|
/** Last position sent to client via the Relative Move or Teleport packets (not Velocity)
|
||||||
|
Only updated if cEntity::BroadcastMovementUpdate() is called! */
|
||||||
|
Vector3d m_LastSentPosition;
|
||||||
|
|
||||||
/** Measured in meter / second */
|
/** Measured in meter / second */
|
||||||
Vector3d m_WaterSpeed;
|
Vector3d m_WaterSpeed;
|
||||||
|
@ -55,7 +55,6 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
|
|||||||
m_FoodSaturationLevel(5.0),
|
m_FoodSaturationLevel(5.0),
|
||||||
m_FoodTickTimer(0),
|
m_FoodTickTimer(0),
|
||||||
m_FoodExhaustionLevel(0.0),
|
m_FoodExhaustionLevel(0.0),
|
||||||
m_LastJumpHeight(0),
|
|
||||||
m_LastGroundHeight(0),
|
m_LastGroundHeight(0),
|
||||||
m_bTouchGround(false),
|
m_bTouchGround(false),
|
||||||
m_Stance(0.0),
|
m_Stance(0.0),
|
||||||
@ -113,7 +112,6 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LastJumpHeight = static_cast<float>(GetPosY());
|
|
||||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
m_LastGroundHeight = static_cast<float>(GetPosY());
|
||||||
m_Stance = GetPosY() + 1.62;
|
m_Stance = GetPosY() + 1.62;
|
||||||
|
|
||||||
@ -244,23 +242,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
SendExperience();
|
SendExperience();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanMove = true;
|
BroadcastMovementUpdate(m_ClientHandle.get());
|
||||||
if (!GetPosition().EqualsEps(m_LastPos, 0.02)) // Non negligible change in position from last tick? 0.02 tp prevent continous calling while floating sometimes.
|
|
||||||
{
|
|
||||||
// Apply food exhaustion from movement:
|
|
||||||
ApplyFoodExhaustionFromMovement();
|
|
||||||
|
|
||||||
if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this, m_LastPos, GetPosition()))
|
|
||||||
{
|
|
||||||
CanMove = false;
|
|
||||||
TeleportToCoords(m_LastPos.x, m_LastPos.y, m_LastPos.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanMove)
|
|
||||||
{
|
|
||||||
BroadcastMovementUpdate(m_ClientHandle.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Health > 0) // make sure player is alive
|
if (m_Health > 0) // make sure player is alive
|
||||||
{
|
{
|
||||||
@ -289,11 +271,6 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
m_LastPlayerListTime = std::chrono::steady_clock::now();
|
m_LastPlayerListTime = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFlying())
|
|
||||||
{
|
|
||||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_TicksUntilNextSave == 0)
|
if (m_TicksUntilNextSave == 0)
|
||||||
{
|
{
|
||||||
SaveToDisk();
|
SaveToDisk();
|
||||||
@ -474,61 +451,88 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bTouchGround = a_bTouchGround;
|
/* Not pretty looking, and is more suited to wherever server-sided collision detection is implemented.
|
||||||
|
The following condition sets on-ground-ness if
|
||||||
|
The player isn't swimming or flying (client hardcoded conditions) and
|
||||||
|
they're on a block (Y is exact) - ensure any they could be standing on (including on the edges) is solid or
|
||||||
|
they're on a slab (Y significand is 0.5) - ditto with slab check
|
||||||
|
they're on a snow layer (Y divisible by 0.125) - ditto with snow layer check
|
||||||
|
*/
|
||||||
|
|
||||||
if (!m_bTouchGround)
|
static const auto HalfWidth = GetWidth() / 2;
|
||||||
{
|
static const auto EPS = 0.0001;
|
||||||
if (GetPosY() > m_LastJumpHeight)
|
if (
|
||||||
{
|
!IsSwimming() && !IsFlying() &&
|
||||||
m_LastJumpHeight = static_cast<float>(GetPosY());
|
(
|
||||||
}
|
(
|
||||||
cWorld * World = GetWorld();
|
((GetPosY() >= 1) && ((GetPosY() - POSY_TOINT) <= EPS)) &&
|
||||||
if ((GetPosY() >= 0) && (GetPosY() < cChunkDef::Height))
|
(
|
||||||
{
|
cBlockInfo::IsSolid(GetWorld()->GetBlock((GetPosition() + Vector3d(0, -1, 0)).Floor())) ||
|
||||||
BLOCKTYPE BlockType = World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT);
|
cBlockInfo::IsSolid(GetWorld()->GetBlock((GetPosition() + Vector3d(HalfWidth, -1, 0)).Floor())) ||
|
||||||
if (BlockType != E_BLOCK_AIR)
|
cBlockInfo::IsSolid(GetWorld()->GetBlock((GetPosition() + Vector3d(-HalfWidth, -1, 0)).Floor())) ||
|
||||||
{
|
cBlockInfo::IsSolid(GetWorld()->GetBlock((GetPosition() + Vector3d(0, -1, HalfWidth)).Floor())) ||
|
||||||
m_bTouchGround = true;
|
cBlockInfo::IsSolid(GetWorld()->GetBlock((GetPosition() + Vector3d(0, -1, -HalfWidth)).Floor()))
|
||||||
}
|
)
|
||||||
if (
|
) ||
|
||||||
(BlockType == E_BLOCK_WATER) ||
|
(
|
||||||
(BlockType == E_BLOCK_STATIONARY_WATER) ||
|
((GetPosY() >= POSY_TOINT) && ((GetPosY() - (POSY_TOINT + 0.5)) <= EPS)) &&
|
||||||
(BlockType == E_BLOCK_LADDER) ||
|
(
|
||||||
(BlockType == E_BLOCK_VINES)
|
cBlockSlabHandler::IsAnySlabType(GetWorld()->GetBlock((GetPosition() + Vector3d(0, 0, 0)).Floor())) ||
|
||||||
|
cBlockSlabHandler::IsAnySlabType(GetWorld()->GetBlock((GetPosition() + Vector3d(HalfWidth, 0, 0)).Floor())) ||
|
||||||
|
cBlockSlabHandler::IsAnySlabType(GetWorld()->GetBlock((GetPosition() + Vector3d(-HalfWidth, 0, 0)).Floor())) ||
|
||||||
|
cBlockSlabHandler::IsAnySlabType(GetWorld()->GetBlock((GetPosition() + Vector3d(0, 0, HalfWidth)).Floor())) ||
|
||||||
|
cBlockSlabHandler::IsAnySlabType(GetWorld()->GetBlock((GetPosition() + Vector3d(0, 0, -HalfWidth)).Floor()))
|
||||||
|
)
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
(fmod(GetPosY(), 0.125) <= EPS) &&
|
||||||
|
(
|
||||||
|
(GetWorld()->GetBlock((GetPosition() + Vector3d(0, 0, 0)).Floor()) == E_BLOCK_SNOW) ||
|
||||||
|
(GetWorld()->GetBlock((GetPosition() + Vector3d(HalfWidth, 0, 0)).Floor()) == E_BLOCK_SNOW) ||
|
||||||
|
(GetWorld()->GetBlock((GetPosition() + Vector3d(-HalfWidth, 0, 0)).Floor()) == E_BLOCK_SNOW) ||
|
||||||
|
(GetWorld()->GetBlock((GetPosition() + Vector3d(0, 0, HalfWidth)).Floor()) == E_BLOCK_SNOW) ||
|
||||||
|
(GetWorld()->GetBlock((GetPosition() + Vector3d(0, 0, -HalfWidth)).Floor()) == E_BLOCK_SNOW)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
{
|
)
|
||||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
float Dist = static_cast<float>(m_LastGroundHeight - floor(GetPosY()));
|
auto Damage = static_cast<int>(m_LastGroundHeight - GetPosY() - 3.0);
|
||||||
|
|
||||||
if (Dist >= 2.0) // At least two blocks - TODO: Use m_LastJumpHeight instead of m_LastGroundHeight above
|
|
||||||
{
|
|
||||||
// Increment statistic
|
|
||||||
m_Stats.AddValue(statDistFallen, FloorC<StatValue>(Dist * 100 + 0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
int Damage = static_cast<int>(Dist - 3.f);
|
|
||||||
if (m_LastJumpHeight > m_LastGroundHeight)
|
|
||||||
{
|
|
||||||
Damage++;
|
|
||||||
}
|
|
||||||
m_LastJumpHeight = static_cast<float>(GetPosY());
|
|
||||||
|
|
||||||
if (Damage > 0)
|
if (Damage > 0)
|
||||||
{
|
{
|
||||||
// cPlayer makes sure damage isn't applied in creative, no need to check here
|
// cPlayer makes sure damage isn't applied in creative, no need to check here
|
||||||
TakeDamage(dtFalling, nullptr, Damage, Damage, 0);
|
TakeDamage(dtFalling, nullptr, Damage, Damage, 0);
|
||||||
|
|
||||||
// Fall particles
|
// Fall particles
|
||||||
GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, static_cast<int>(GetPosY()) - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
|
Damage = std::min(15, Damage);
|
||||||
|
GetClientHandle()->SendParticleEffect(
|
||||||
|
"blockdust",
|
||||||
|
GetPosition(),
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
(Damage - 1.f) * ((0.3f - 0.1f) / (15.f - 1.f)) + 0.1f, // Map damage (1 - 15) to particle speed (0.1 - 0.3)
|
||||||
|
static_cast<int>((Damage - 1.f) * ((50.f - 20.f) / (15.f - 1.f)) + 20.f), // Map damage (1 - 15) to particle quantity (20 - 50)
|
||||||
|
{ { GetWorld()->GetBlock(POS_TOINT - Vector3i(0, 1, 0)), 0 } }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
m_bTouchGround = true;
|
||||||
|
m_LastGroundHeight = GetPosY();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_bTouchGround = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsFlying() || IsSwimming() || IsClimbing())
|
||||||
|
{
|
||||||
|
m_LastGroundHeight = GetPosY();
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED(a_bTouchGround);
|
||||||
|
/* Unfortunately whatever the reason, there are still desyncs in on-ground status between the client and server. For example:
|
||||||
|
1. Walking off a ledge (whatever height)
|
||||||
|
2. Initial login
|
||||||
|
Thus, it is too risky to compare their value against ours and kick them for hacking */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1322,11 +1326,10 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach)
|
|||||||
void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
||||||
{
|
{
|
||||||
// ask plugins to allow teleport to the new position.
|
// ask plugins to allow teleport to the new position.
|
||||||
if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPos, Vector3d(a_PosX, a_PosY, a_PosZ)))
|
if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ)))
|
||||||
{
|
{
|
||||||
SetPosition(a_PosX, a_PosY, a_PosZ);
|
SetPosition(a_PosX, a_PosY, a_PosZ);
|
||||||
m_LastGroundHeight = static_cast<float>(a_PosY);
|
m_LastGroundHeight = static_cast<float>(a_PosY);
|
||||||
m_LastJumpHeight = static_cast<float>(a_PosY);
|
|
||||||
m_bIsTeleporting = true;
|
m_bIsTeleporting = true;
|
||||||
|
|
||||||
m_World->BroadcastTeleportEntity(*this, GetClientHandle());
|
m_World->BroadcastTeleportEntity(*this, GetClientHandle());
|
||||||
@ -1400,37 +1403,6 @@ void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::MoveTo( const Vector3d & a_NewPos)
|
|
||||||
{
|
|
||||||
if ((a_NewPos.y < -990) && (GetPosY() > -100))
|
|
||||||
{
|
|
||||||
// When attached to an entity, the client sends position packets with weird coords:
|
|
||||||
// Y = -999 and X, Z = attempting to create speed, usually up to 0.03
|
|
||||||
// We cannot test m_AttachedTo, because when deattaching, the server thinks the client is already deattached while
|
|
||||||
// the client may still send more of these nonsensical packets.
|
|
||||||
if (m_AttachedTo != nullptr)
|
|
||||||
{
|
|
||||||
Vector3d AddSpeed(a_NewPos);
|
|
||||||
AddSpeed.y = 0;
|
|
||||||
m_AttachedTo->AddSpeed(AddSpeed);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: should do some checks to see if player is not moving through terrain
|
|
||||||
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too
|
|
||||||
|
|
||||||
Vector3d DeltaPos = a_NewPos - GetPosition();
|
|
||||||
UpdateMovementStats(DeltaPos);
|
|
||||||
|
|
||||||
SetPosition( a_NewPos);
|
|
||||||
SetStance(a_NewPos.y + 1.62);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::SetVisible(bool a_bVisible)
|
void cPlayer::SetVisible(bool a_bVisible)
|
||||||
{
|
{
|
||||||
// Need to Check if the player or other players are in gamemode spectator, but will break compatibility
|
// Need to Check if the player or other players are in gamemode spectator, but will break compatibility
|
||||||
@ -1784,7 +1756,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
|||||||
SetPosX(JSON_PlayerPosition[0].asDouble());
|
SetPosX(JSON_PlayerPosition[0].asDouble());
|
||||||
SetPosY(JSON_PlayerPosition[1].asDouble());
|
SetPosY(JSON_PlayerPosition[1].asDouble());
|
||||||
SetPosZ(JSON_PlayerPosition[2].asDouble());
|
SetPosZ(JSON_PlayerPosition[2].asDouble());
|
||||||
m_LastPos = GetPosition();
|
m_LastPosition = GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value & JSON_PlayerRotation = root["rotation"];
|
Json::Value & JSON_PlayerRotation = root["rotation"];
|
||||||
@ -2102,12 +2074,23 @@ bool cPlayer::IsClimbing(void) const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
|
void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround)
|
||||||
{
|
{
|
||||||
StatValue Value = FloorC<StatValue>(a_DeltaPos.Length() * 100 + 0.5);
|
if (m_bIsTeleporting)
|
||||||
|
{
|
||||||
|
m_bIsTeleporting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatValue Value = FloorC<StatValue>(a_DeltaPos.Length() * 100 + 0.5);
|
||||||
if (m_AttachedTo == nullptr)
|
if (m_AttachedTo == nullptr)
|
||||||
{
|
{
|
||||||
|
if (IsFlying())
|
||||||
|
{
|
||||||
|
m_Stats.AddValue(statDistFlown, Value);
|
||||||
|
// May be flying and doing any of the following:
|
||||||
|
}
|
||||||
|
|
||||||
if (IsClimbing())
|
if (IsClimbing())
|
||||||
{
|
{
|
||||||
if (a_DeltaPos.y > 0.0) // Going up
|
if (a_DeltaPos.y > 0.0) // Going up
|
||||||
@ -2128,14 +2111,22 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
|
|||||||
else if (IsOnGround())
|
else if (IsOnGround())
|
||||||
{
|
{
|
||||||
m_Stats.AddValue(statDistWalked, Value);
|
m_Stats.AddValue(statDistWalked, Value);
|
||||||
AddFoodExhaustion((m_IsSprinting ? 0.001 : 0.0001) * static_cast<double>(Value));
|
AddFoodExhaustion((IsSprinting() ? 0.001 : 0.0001) * static_cast<double>(Value));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Value >= 25) // Ignore small / slow movement
|
// If a jump just started, process food exhaustion:
|
||||||
|
if ((a_DeltaPos.y > 0.0) && a_PreviousIsOnGround)
|
||||||
{
|
{
|
||||||
m_Stats.AddValue(statDistFlown, Value);
|
m_Stats.AddValue(statJumps, 1);
|
||||||
|
AddFoodExhaustion((IsSprinting() ? 0.008 : 0.002) * static_cast<double>(Value));
|
||||||
}
|
}
|
||||||
|
else if (a_DeltaPos.y < 0.0)
|
||||||
|
{
|
||||||
|
// Increment statistic
|
||||||
|
m_Stats.AddValue(statDistFallen, (StatValue)(abs(a_DeltaPos.y) * 100 + 0.5));
|
||||||
|
}
|
||||||
|
// TODO: good opportunity to detect illegal flight (check for falling tho)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2164,59 +2155,6 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::ApplyFoodExhaustionFromMovement()
|
|
||||||
{
|
|
||||||
if (IsGameModeCreative() || IsGameModeSpectator())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have just teleported, apply no exhaustion
|
|
||||||
if (m_bIsTeleporting)
|
|
||||||
{
|
|
||||||
m_bIsTeleporting = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If riding anything, apply no food exhaustion
|
|
||||||
if (m_AttachedTo != nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the distance travelled, update the last pos:
|
|
||||||
double SpeedX = m_Speed.x;
|
|
||||||
double SpeedZ = m_Speed.z;
|
|
||||||
double BaseExhaustion(sqrt((SpeedX * SpeedX) + (SpeedZ * SpeedZ)));
|
|
||||||
|
|
||||||
// Apply the exhaustion based on distance travelled:
|
|
||||||
if (IsFlying() || IsClimbing())
|
|
||||||
{
|
|
||||||
// Apply no exhaustion when flying or climbing.
|
|
||||||
BaseExhaustion = 0;
|
|
||||||
}
|
|
||||||
else if (IsSprinting())
|
|
||||||
{
|
|
||||||
// 0.1 pt per meter sprinted
|
|
||||||
BaseExhaustion = BaseExhaustion * 0.1;
|
|
||||||
}
|
|
||||||
else if (IsSwimming())
|
|
||||||
{
|
|
||||||
// 0.015 pt per meter swum
|
|
||||||
BaseExhaustion = BaseExhaustion * 0.015;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 0.01 pt per meter walked / sneaked
|
|
||||||
BaseExhaustion = BaseExhaustion * 0.01;
|
|
||||||
}
|
|
||||||
m_FoodExhaustionLevel += BaseExhaustion;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::LoadRank(void)
|
void cPlayer::LoadRank(void)
|
||||||
{
|
{
|
||||||
// Load the values from cRankManager:
|
// Load the values from cRankManager:
|
||||||
|
@ -117,8 +117,8 @@ public:
|
|||||||
/** Returns true if the player is currently charging the bow */
|
/** Returns true if the player is currently charging the bow */
|
||||||
bool IsChargingBow(void) const { return m_IsChargingBow; }
|
bool IsChargingBow(void) const { return m_IsChargingBow; }
|
||||||
|
|
||||||
void SetTouchGround( bool a_bTouchGround);
|
void SetTouchGround(bool a_bTouchGround);
|
||||||
inline void SetStance( const double a_Stance) { m_Stance = a_Stance; }
|
inline void SetStance(const double a_Stance) { m_Stance = a_Stance; }
|
||||||
double GetEyeHeight(void) const; // tolua_export
|
double GetEyeHeight(void) const; // tolua_export
|
||||||
Vector3d GetEyePosition(void) const; // tolua_export
|
Vector3d GetEyePosition(void) const; // tolua_export
|
||||||
virtual bool IsOnGround(void) const override { return m_bTouchGround; }
|
virtual bool IsOnGround(void) const override { return m_bTouchGround; }
|
||||||
@ -208,9 +208,6 @@ public:
|
|||||||
@deprecated Use SetSpeed instead. */
|
@deprecated Use SetSpeed instead. */
|
||||||
void ForceSetSpeed(const Vector3d & a_Speed); // tolua_export
|
void ForceSetSpeed(const Vector3d & a_Speed); // tolua_export
|
||||||
|
|
||||||
/** Tries to move to a new position, with attachment-related checks (y == -999) */
|
|
||||||
void MoveTo(const Vector3d & a_NewPos); // tolua_export
|
|
||||||
|
|
||||||
cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export
|
cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export
|
||||||
const cWindow * GetWindow(void) const { return m_CurrentWindow; }
|
const cWindow * GetWindow(void) const { return m_CurrentWindow; }
|
||||||
|
|
||||||
@ -454,7 +451,7 @@ public:
|
|||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
/** Update movement-related statistics. */
|
/** Update movement-related statistics. */
|
||||||
void UpdateMovementStats(const Vector3d & a_DeltaPos);
|
void UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround);
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
@ -553,8 +550,7 @@ protected:
|
|||||||
/** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */
|
/** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */
|
||||||
double m_FoodExhaustionLevel;
|
double m_FoodExhaustionLevel;
|
||||||
|
|
||||||
float m_LastJumpHeight;
|
double m_LastGroundHeight;
|
||||||
float m_LastGroundHeight;
|
|
||||||
bool m_bTouchGround;
|
bool m_bTouchGround;
|
||||||
double m_Stance;
|
double m_Stance;
|
||||||
|
|
||||||
@ -667,9 +663,6 @@ protected:
|
|||||||
/** Tosses a list of items. */
|
/** Tosses a list of items. */
|
||||||
void TossItems(const cItems & a_Items);
|
void TossItems(const cItems & a_Items);
|
||||||
|
|
||||||
/** Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) */
|
|
||||||
void ApplyFoodExhaustionFromMovement();
|
|
||||||
|
|
||||||
/** Returns the filename for the player data based on the UUID given.
|
/** Returns the filename for the player data based on the UUID given.
|
||||||
This can be used both for online and offline UUIDs. */
|
This can be used both for online and offline UUIDs. */
|
||||||
AString GetUUIDFileName(const AString & a_UUID);
|
AString GetUUIDFileName(const AString & a_UUID);
|
||||||
|
@ -1028,10 +1028,7 @@ void cProtocol180::SendPlayerMoveLook(void)
|
|||||||
cPacketizer Pkt(*this, 0x08); // Player Position And Look packet
|
cPacketizer Pkt(*this, 0x08); // Player Position And Look packet
|
||||||
cPlayer * Player = m_Client->GetPlayer();
|
cPlayer * Player = m_Client->GetPlayer();
|
||||||
Pkt.WriteBEDouble(Player->GetPosX());
|
Pkt.WriteBEDouble(Player->GetPosX());
|
||||||
|
Pkt.WriteBEDouble(Player->GetPosY());
|
||||||
// The "+ 0.001" is there because otherwise the player falls through the block they were standing on.
|
|
||||||
Pkt.WriteBEDouble(Player->GetPosY() + 0.001);
|
|
||||||
|
|
||||||
Pkt.WriteBEDouble(Player->GetPosZ());
|
Pkt.WriteBEDouble(Player->GetPosZ());
|
||||||
Pkt.WriteBEFloat(static_cast<float>(Player->GetYaw()));
|
Pkt.WriteBEFloat(static_cast<float>(Player->GetYaw()));
|
||||||
Pkt.WriteBEFloat(static_cast<float>(Player->GetPitch()));
|
Pkt.WriteBEFloat(static_cast<float>(Player->GetPitch()));
|
||||||
|
Loading…
Reference in New Issue
Block a user