summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Entity.cpp22
-rw-r--r--src/Entities/Entity.h29
-rw-r--r--src/Entities/Minecart.cpp6
-rw-r--r--src/Entities/Minecart.h9
-rw-r--r--src/Entities/Pawn.cpp5
-rw-r--r--src/Entities/Player.cpp306
-rw-r--r--src/Entities/Player.h173
7 files changed, 368 insertions, 182 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index f1d8c989d..a6f7dd58c 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -59,6 +59,8 @@ cEntity::cEntity(eEntityType a_EntityType, Vector3d a_Pos, double a_Width, doubl
m_IsInLava(false),
m_IsInWater(false),
m_IsHeadInWater(false),
+ m_Width(a_Width),
+ m_Height(a_Height),
m_AirLevel(MAX_AIR_LEVEL),
m_AirTickTimer(DROWNING_TICKS),
m_TicksAlive(0),
@@ -69,8 +71,6 @@ cEntity::cEntity(eEntityType a_EntityType, Vector3d a_Pos, double a_Width, doubl
m_Position(a_Pos),
m_WaterSpeed(0, 0, 0),
m_Mass (0.001), // Default 1g
- m_Width(a_Width),
- m_Height(a_Height),
m_InvulnerableTicks(0)
{
m_WorldChangeInfo.m_NewWorld = nullptr;
@@ -2028,15 +2028,6 @@ void cEntity::SetHeadYaw(double a_HeadYaw)
-void cEntity::SetHeight(double a_Height)
-{
- m_Height = a_Height;
-}
-
-
-
-
-
void cEntity::SetMass(double a_Mass)
{
// Make sure that mass is not zero. 1g is the default because we
@@ -2118,15 +2109,6 @@ void cEntity::SetSpeedZ(double a_SpeedZ)
-void cEntity::SetWidth(double a_Width)
-{
- m_Width = a_Width;
-}
-
-
-
-
-
void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ)
{
SetSpeed(m_Speed.x + a_AddSpeedX, m_Speed.y + a_AddSpeedY, m_Speed.z + a_AddSpeedZ);
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 9fe7f16f5..559f4eb66 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -328,10 +328,6 @@ public:
// tolua_end
- void SetHeight(double a_Height);
-
- void SetWidth(double a_Width);
-
/** Exported in ManualBindings */
const Vector3d & GetPosition(void) const { return m_Position; }
@@ -522,12 +518,13 @@ public:
// tolua_begin
// COMMON metadata flags; descendants may override the defaults:
- virtual bool IsOnFire (void) const {return (m_TicksLeftBurning > 0); }
- virtual bool IsCrouched (void) const {return false; }
- virtual bool IsRiding (void) const {return false; }
- virtual bool IsSprinting(void) const {return false; }
- virtual bool IsRclking (void) const {return false; }
- virtual bool IsInvisible(void) const { return false; }
+ virtual bool IsCrouched (void) const { return false; }
+ virtual bool IsElytraFlying(void) const { return false; }
+ virtual bool IsInvisible (void) const { return false; }
+ virtual bool IsOnFire (void) const { return m_TicksLeftBurning > 0; }
+ virtual bool IsRclking (void) const { return false; }
+ virtual bool IsRiding (void) const { return false; }
+ virtual bool IsSprinting (void) const { return false; }
/** Returns true if any part of the entity is in a fire block */
virtual bool IsInFire(void) const { return m_IsInFire; }
@@ -689,6 +686,12 @@ protected:
/** If the entity's head is in a water block */
bool m_IsHeadInWater;
+ /** Width of the entity, in the XZ plane. Since entities are represented as cylinders, this is more of a diameter. */
+ double m_Width;
+
+ /** Height of the entity (Y axis). */
+ double m_Height;
+
/** Air level of a mobile */
int m_AirLevel;
int m_AirTickTimer;
@@ -745,12 +748,6 @@ private:
/** Measured in Kilograms (Kg) */
double m_Mass;
- /** Width of the entity, in the XZ plane. Since entities are represented as cylinders, this is more of a diameter. */
- double m_Width;
-
- /** Height of the entity (Y axis) */
- double m_Height;
-
/** If a player hit a entity, the entity receive a invulnerable of 10 ticks.
While this ticks, a player can't hit this entity. */
int m_InvulnerableTicks;
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index 5fc67db5a..c4636c5b1 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -106,8 +106,6 @@ cMinecart::cMinecart(ePayload a_Payload, Vector3d a_Pos):
SetAirDrag(0.05f);
SetMaxHealth(6);
SetHealth(6);
- SetWidth(1);
- SetHeight(0.9);
}
@@ -1274,10 +1272,10 @@ void cMinecart::ApplyAcceleration(Vector3d a_ForwardDirection, double a_Accelera
////////////////////////////////////////////////////////////////////////////////
// cRideableMinecart:
-cRideableMinecart::cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_Height):
+cRideableMinecart::cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_ContentHeight):
Super(mpNone, a_Pos),
m_Content(a_Content),
- m_Height(a_Height)
+ m_ContentHeight(a_ContentHeight)
{
}
diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h
index a98014799..0d62d98f1 100644
--- a/src/Entities/Minecart.h
+++ b/src/Entities/Minecart.h
@@ -105,10 +105,10 @@ public:
CLASS_PROTODEF(cRideableMinecart)
- cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_Height);
+ cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_ContentHeight);
- const cItem & GetContent(void) const {return m_Content;}
- int GetBlockHeight(void) const {return m_Height;}
+ const cItem & GetContent(void) const { return m_Content; }
+ int GetBlockHeight(void) const { return m_ContentHeight; }
// cEntity overrides:
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
@@ -116,9 +116,8 @@ public:
protected:
-
cItem m_Content;
- int m_Height;
+ int m_ContentHeight;
} ;
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index 6f33a5eca..a58c1dc40 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -418,6 +418,11 @@ void cPawn::HandleFalling(void)
auto Damage = static_cast<int>(m_LastGroundHeight - GetPosY() - 3.0);
if ((Damage > 0) && !FallDamageAbsorbed)
{
+ if (IsElytraFlying())
+ {
+ Damage = static_cast<int>(static_cast<float>(Damage) * 0.33);
+ }
+
TakeDamage(dtFalling, nullptr, Damage, static_cast<float>(Damage), 0);
// Fall particles
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 9497d326b..a727429d4 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -66,38 +66,72 @@ const int cPlayer::EATING_TICKS = 30;
+cPlayer::BodyStanceCrouching::BodyStanceCrouching(cPlayer & a_Player)
+{
+ a_Player.SetSize(0.6f, 1.65f);
+}
+
+
+
+
+
+cPlayer::BodyStanceSleeping::BodyStanceSleeping(cPlayer & a_Player)
+{
+ a_Player.SetSize(0.2f, 0.2f);
+}
+
+
+
+
+
+cPlayer::BodyStanceStanding::BodyStanceStanding(cPlayer & a_Player)
+{
+ a_Player.SetSize(0.6f, 1.8f);
+}
+
+
+
+
+
+cPlayer::BodyStanceGliding::BodyStanceGliding(cPlayer & a_Player) :
+ TicksElytraFlying(0)
+{
+ a_Player.SetSize(0.6f, 0.6f);
+}
+
+
+
+
+
cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) :
Super(etPlayer, 0.6, 1.8),
- m_bVisible(true),
+ m_BodyStance(BodyStanceStanding(*this)),
m_FoodLevel(MAX_FOOD_LEVEL),
m_FoodSaturationLevel(5.0),
m_FoodTickTimer(0),
m_FoodExhaustionLevel(0.0),
- m_Stance(0.0),
m_Inventory(*this),
m_EnderChestContents(9, 3),
m_DefaultWorldPath(cRoot::Get()->GetDefaultWorld()->GetDataPath()),
m_GameMode(eGameMode_NotSet),
m_ClientHandle(a_Client),
- m_IsFrozen(false),
m_NormalMaxSpeed(1.0),
m_SprintingMaxSpeed(1.3),
m_FlyingMaxSpeed(1.0),
- m_IsCrouched(false),
- m_IsSprinting(false),
- m_IsFlying(false),
+ m_IsChargingBow(false),
m_IsFishing(false),
- m_CanFly(false),
+ m_IsFlightCapable(false),
+ m_IsFlying(false),
+ m_IsFrozen(false),
+ m_IsTeleporting(false),
+ m_IsVisible(true),
m_EatingFinishTick(-1),
m_LifetimeTotalXp(0),
m_CurrentXp(0),
- m_IsChargingBow(false),
m_BowCharge(0),
m_FloaterID(cEntity::INVALID_ID),
m_Team(nullptr),
- m_bIsInBed(false),
m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
- m_bIsTeleporting(false),
m_SkinParts(0),
m_MainHand(mhRight)
{
@@ -114,26 +148,25 @@ cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) :
LoadFromDisk(World);
m_LastGroundHeight = static_cast<float>(GetPosY());
- m_Stance = GetPosY() + 1.62;
if (m_GameMode == gmNotSet)
{
if (World->IsGameModeCreative())
{
- m_CanFly = true;
+ m_IsFlightCapable = true;
}
if (World->IsGameModeSpectator()) // Otherwise Player will fall out of the world on join
{
- m_CanFly = true;
+ m_IsFlightCapable = true;
m_IsFlying = true;
}
}
if (m_GameMode == gmSpectator) // If player is reconnecting to the server in spectator mode
{
- m_CanFly = true;
+ m_IsFlightCapable = true;
m_IsFlying = true;
- m_bVisible = false;
+ m_IsVisible = false;
}
}
@@ -427,6 +460,24 @@ void cPlayer::AddFoodExhaustion(double a_Exhaustion)
+bool cPlayer::IsInBed(void) const
+{
+ return std::holds_alternative<BodyStanceSleeping>(m_BodyStance);
+}
+
+
+
+
+
+bool cPlayer::IsStanding() const
+{
+ return std::holds_alternative<BodyStanceStanding>(m_BodyStance);
+}
+
+
+
+
+
void cPlayer::TossItems(const cItems & a_Items)
{
if (IsGameModeSpectator()) // Players can't toss items in spectator
@@ -445,6 +496,23 @@ void cPlayer::TossItems(const cItems & a_Items)
+void cPlayer::SetIsInBed(const bool a_GoToBed)
+{
+ if (a_GoToBed && IsStanding())
+ {
+ m_BodyStance = BodyStanceSleeping(*this);
+ }
+ else if (!a_GoToBed && IsInBed())
+ {
+ m_BodyStance = BodyStanceStanding(*this);
+ GetWorld()->BroadcastEntityAnimation(*this, 2);
+ }
+}
+
+
+
+
+
void cPlayer::StartEating(void)
{
// Set the timer:
@@ -525,11 +593,11 @@ const cSlotNums & cPlayer::GetInventoryPaintSlots(void) const
double cPlayer::GetMaxSpeed(void) const
{
- if (m_IsFlying)
+ if (IsFlying())
{
return m_FlyingMaxSpeed;
}
- else if (m_IsSprinting)
+ else if (IsSprinting())
{
return m_SprintingMaxSpeed;
}
@@ -546,7 +614,7 @@ double cPlayer::GetMaxSpeed(void) const
void cPlayer::SetNormalMaxSpeed(double a_Speed)
{
m_NormalMaxSpeed = a_Speed;
- if (!m_IsSprinting && !m_IsFlying && !m_IsFrozen)
+ if (!IsSprinting() && !IsFlying() && !IsFrozen())
{
// If we are frozen, we do not send this yet. We send when unfreeze() is called
m_ClientHandle->SendPlayerMaxSpeed();
@@ -560,7 +628,7 @@ void cPlayer::SetNormalMaxSpeed(double a_Speed)
void cPlayer::SetSprintingMaxSpeed(double a_Speed)
{
m_SprintingMaxSpeed = a_Speed;
- if (m_IsSprinting && !m_IsFlying && !m_IsFrozen)
+ if (IsSprinting() && !m_IsFlying && !m_IsFrozen)
{
// If we are frozen, we do not send this yet. We send when unfreeze() is called
m_ClientHandle->SendPlayerMaxSpeed();
@@ -587,21 +655,36 @@ void cPlayer::SetFlyingMaxSpeed(double a_Speed)
-void cPlayer::SetCrouch(bool a_IsCrouched)
+void cPlayer::SetCrouch(const bool a_ShouldCrouch)
{
- // Set the crouch status, broadcast to all visible players
- if (a_IsCrouched == m_IsCrouched)
+ if (a_ShouldCrouch && IsStanding())
{
- // No change
- return;
+ m_BodyStance = BodyStanceCrouching(*this);
+ cRoot::Get()->GetPluginManager()->CallHookPlayerCrouched(*this);
}
+ else if (!a_ShouldCrouch && IsCrouched())
+ {
+ m_BodyStance = BodyStanceStanding(*this);
+ }
+
+ m_World->BroadcastEntityMetadata(*this);
+}
- if (a_IsCrouched)
+
+
+
+
+void cPlayer::SetElytraFlight(const bool a_ShouldElytraFly)
+{
+ if (a_ShouldElytraFly && IsStanding() && !IsOnGround() && !IsInWater() && !IsRiding() && (GetEquippedChestplate().m_ItemType == E_ITEM_ELYTRA))
{
- cRoot::Get()->GetPluginManager()->CallHookPlayerCrouched(*this);
+ m_BodyStance = BodyStanceGliding(*this);
+ }
+ else if (!a_ShouldElytraFly && IsElytraFlying())
+ {
+ m_BodyStance = BodyStanceStanding(*this);
}
- m_IsCrouched = a_IsCrouched;
m_World->BroadcastEntityMetadata(*this);
}
@@ -609,16 +692,37 @@ void cPlayer::SetCrouch(bool a_IsCrouched)
-void cPlayer::SetSprint(bool a_IsSprinting)
+void cPlayer::SetFlying(const bool a_ShouldFly)
{
- if (a_IsSprinting == m_IsSprinting)
+ if (a_ShouldFly == m_IsFlying)
{
- // No change
return;
}
- m_IsSprinting = a_IsSprinting;
- m_ClientHandle->SendPlayerMaxSpeed();
+ m_IsFlying = a_ShouldFly;
+ if (!m_IsFrozen)
+ {
+ // If we are frozen, we do not send this yet. We send when unfreeze() is called
+ m_ClientHandle->SendPlayerAbilities();
+ }
+}
+
+
+
+
+
+void cPlayer::SetSprint(const bool a_ShouldSprint)
+{
+ if (a_ShouldSprint && IsStanding())
+ {
+ m_BodyStance = BodyStanceSprinting();
+ }
+ else if (!a_ShouldSprint && IsSprinting())
+ {
+ m_BodyStance = BodyStanceStanding(*this);
+ }
+
+ m_World->BroadcastEntityMetadata(*this);
}
@@ -627,12 +731,12 @@ void cPlayer::SetSprint(bool a_IsSprinting)
void cPlayer::SetCanFly(bool a_CanFly)
{
- if (a_CanFly == m_CanFly)
+ if (a_CanFly == m_IsFlightCapable)
{
return;
}
- m_CanFly = a_CanFly;
+ m_IsFlightCapable = a_CanFly;
m_ClientHandle->SendPlayerAbilities();
}
@@ -698,25 +802,6 @@ cWorld * cPlayer::GetBedWorld()
-void cPlayer::SetFlying(bool a_IsFlying)
-{
- if (a_IsFlying == m_IsFlying)
- {
- return;
- }
-
- m_IsFlying = a_IsFlying;
- if (!m_IsFrozen)
- {
- // If we are frozen, we do not send this yet. We send when unfreeze() is called
- m_ClientHandle->SendPlayerAbilities();
- }
-}
-
-
-
-
-
void cPlayer::NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved)
{
ASSERT(a_Opponent != nullptr);
@@ -750,7 +835,7 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
return; // not dead yet =]
}
- m_bVisible = false; // So new clients don't see the player
+ m_IsVisible = false; // So new clients don't see the player
// Detach player from object / entity. If the player dies, the server still says
// that the player is attached to the entity / object
@@ -905,7 +990,7 @@ void cPlayer::Respawn(void)
double cPlayer::GetEyeHeight(void) const
{
- return m_Stance;
+ return GetEyePosition().y - GetPosY();
}
@@ -914,7 +999,22 @@ double cPlayer::GetEyeHeight(void) const
Vector3d cPlayer::GetEyePosition(void) const
{
- return Vector3d( GetPosX(), m_Stance, GetPosZ());
+ if (IsCrouched())
+ {
+ return GetPosition().addedY(1.54);
+ }
+
+ if (IsElytraFlying())
+ {
+ return GetPosition().addedY(0.4);
+ }
+
+ if (IsInBed())
+ {
+ return GetPosition().addedY(0.2);
+ }
+
+ return GetPosition().addedY(1.6);
}
@@ -1314,7 +1414,7 @@ void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
{
SetPosition({a_PosX, a_PosY, a_PosZ});
FreezeInternal(GetPosition(), false);
- m_bIsTeleporting = true;
+ m_IsTeleporting = true;
m_ClientHandle->SendPlayerMoveLook();
}
@@ -1344,6 +1444,11 @@ bool cPlayer::IsFrozen()
void cPlayer::Unfreeze()
{
+ if (IsElytraFlying())
+ {
+ m_World->BroadcastEntityMetadata(*this);
+ }
+
GetClientHandle()->SendPlayerAbilities();
GetClientHandle()->SendPlayerMaxSpeed();
@@ -1449,14 +1554,14 @@ void cPlayer::ForceSetSpeed(const Vector3d & a_Speed)
void cPlayer::SetVisible(bool a_bVisible)
{
// Need to Check if the player or other players are in gamemode spectator, but will break compatibility
- if (a_bVisible && !m_bVisible) // Make visible
+ if (a_bVisible && !m_IsVisible) // Make visible
{
- m_bVisible = true;
+ m_IsVisible = true;
m_World->BroadcastSpawnEntity(*this);
}
- if (!a_bVisible && m_bVisible)
+ if (!a_bVisible && m_IsVisible)
{
- m_bVisible = false;
+ m_IsVisible = false;
m_World->BroadcastDestroyEntity(*this, m_ClientHandle.get()); // Destroy on all clients
}
}
@@ -1809,7 +1914,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
if (m_GameMode == eGameMode_Creative)
{
- m_CanFly = true;
+ m_IsFlightCapable = true;
}
m_Inventory.LoadFromJson(Root["inventory"]);
@@ -2141,9 +2246,9 @@ bool cPlayer::IsClimbing(void) const
void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround)
{
- if (m_bIsTeleporting)
+ if (m_IsTeleporting)
{
- m_bIsTeleporting = false;
+ m_IsTeleporting = false;
return;
}
@@ -2599,16 +2704,19 @@ float cPlayer::GetLiquidHeightPercent(NIBBLETYPE a_Meta)
bool cPlayer::IsInsideWater()
{
- BLOCKTYPE Block = m_World->GetBlock(Vector3d(GetPosX(), m_Stance, GetPosZ()).Floor());
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ m_World->GetBlockTypeMeta(GetEyePosition().Floor(), Block, Meta);
+
if ((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER))
{
return false;
}
- NIBBLETYPE Meta = GetWorld()->GetBlockMeta(Vector3d(GetPosX(), m_Stance, GetPosZ()).Floor());
+
+ const auto EyeHeight = GetEyeHeight();
float f = GetLiquidHeightPercent(Meta) - 0.11111111f;
- float f1 = static_cast<float>(m_Stance + 1) - f;
- bool flag = (m_Stance < f1);
- return flag;
+ float f1 = static_cast<float>(EyeHeight + 1) - f;
+ return EyeHeight < f1;
}
@@ -2742,6 +2850,16 @@ void cPlayer::AddKnownItem(const cItem & a_Item)
+void cPlayer::SetSize(const float a_Width, const float a_Height)
+{
+ m_Width = a_Width;
+ m_Height = a_Height;
+}
+
+
+
+
+
void cPlayer::AddKnownRecipe(UInt32 a_RecipeId)
{
auto Response = m_KnownRecipes.insert(a_RecipeId);
@@ -2916,6 +3034,33 @@ float cPlayer::GetEnchantmentBlastKnockbackReduction()
+bool cPlayer::IsCrouched(void) const
+{
+ return std::holds_alternative<BodyStanceCrouching>(m_BodyStance);
+}
+
+
+
+
+
+bool cPlayer::IsElytraFlying(void) const
+{
+ return std::holds_alternative<BodyStanceGliding>(m_BodyStance);
+}
+
+
+
+
+
+bool cPlayer::IsSprinting(void) const
+{
+ return std::holds_alternative<BodyStanceSprinting>(m_BodyStance);
+}
+
+
+
+
+
void cPlayer::OnAddToWorld(cWorld & a_World)
{
Super::OnAddToWorld(a_World);
@@ -3023,7 +3168,7 @@ void cPlayer::OnRemoveFromWorld(cWorld & a_World)
void cPlayer::SpawnOn(cClientHandle & a_Client)
{
- if (!m_bVisible || (m_ClientHandle.get() == (&a_Client)))
+ if (!m_IsVisible || (m_ClientHandle.get() == (&a_Client)))
{
return;
}
@@ -3110,6 +3255,27 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_BowCharge += 1;
}
+ if (IsElytraFlying())
+ {
+ // Damage elytra, once per second:
+ {
+ using namespace std::chrono_literals;
+
+ auto & TicksFlying = std::get<BodyStanceGliding>(m_BodyStance).TicksElytraFlying;
+ const auto TotalFlew = TicksFlying + a_Dt;
+ const auto Periods = static_cast<short>(TotalFlew / 1s);
+ TicksFlying = std::chrono::duration_cast<cTickTime>(TotalFlew - Periods * 1s);
+
+ UseItem(cInventory::invArmorOffset + 1, Periods);
+ }
+
+ // Check if flight is still possible:
+ if (IsOnGround() || IsInWater() || IsRiding() || (GetEquippedChestplate().m_ItemType != E_ITEM_ELYTRA))
+ {
+ SetElytraFlight(false);
+ }
+ }
+
BroadcastMovementUpdate(m_ClientHandle.get());
if (m_Health > 0) // make sure player is alive
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 4d6a41a35..5a17ca783 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -27,11 +27,57 @@ class cTeam;
class cPlayer:
public cPawn
{
-
// tolua_end
using Super = cPawn;
+ /** Tag representing a sneaking pose. */
+ struct BodyStanceCrouching
+ {
+ BodyStanceCrouching(cPlayer & a_Player);
+ };
+
+ /** Tag representing a sleeping pose.
+ Set by a right click on unoccupied bed, unset by a time fast forward or teleport. */
+ struct BodyStanceSleeping
+ {
+ BodyStanceSleeping(cPlayer & a_Player);
+ };
+
+ /** Tag representing a sprinting pose. */
+ struct BodyStanceSprinting
+ {
+ };
+
+ /** Tag representing the neutral stance. */
+ struct BodyStanceStanding
+ {
+ BodyStanceStanding(cPlayer & a_Player);
+ };
+
+ /** Tag representing a swimming or elytra flying pose. */
+ struct BodyStanceGliding
+ {
+ BodyStanceGliding(cPlayer & a_Player);
+
+ cTickTime TicksElytraFlying;
+ };
+
+ /*
+ struct HandStanceNeutral
+ {
+ };
+
+ struct HandStandChargingBow
+ {
+ int m_BowCharge;
+ };
+
+ struct HandStanceEating
+ {
+ };
+ */
+
// tolua_begin
public:
@@ -105,11 +151,8 @@ public:
bool IsChargingBow(void) const { return m_IsChargingBow; }
void SetTouchGround(bool a_bTouchGround);
- inline void SetStance(const double a_Stance) { m_Stance = a_Stance; }
double GetEyeHeight(void) const; // tolua_export
Vector3d GetEyePosition(void) const; // tolua_export
- virtual bool IsOnGround(void) const override { return m_bTouchGround; }
- inline double GetStance(void) const { return m_Stance; } // tolua_export
inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
inline const cInventory & GetInventory(void) const { return m_Inventory; }
@@ -333,8 +376,8 @@ public:
/** Returns true if the player is currently flying */
bool IsFlying(void) const { return m_IsFlying; }
- /** Returns true if a player is sleeping in a bed */
- bool IsInBed(void) const { return m_bIsInBed; }
+ /** Returns true if a player is sleeping in a bed. */
+ bool IsInBed(void) const;
/** Returns true if the player has thrown out a floater */
bool IsFishing(void) const { return m_IsFishing; }
@@ -345,21 +388,16 @@ public:
// tolua_end
+ /** Returns true if a player is standing normally, that is, in a neutral pose. */
+ bool IsStanding() const;
+
/** Tosses a list of items. */
void TossItems(const cItems & a_Items);
- /** Sets a player's in-bed state
- We can't be sure plugins will keep this value updated, so no exporting
- If value is false (not in bed), will update players of the fact that they have been ejected from the bed
- */
- void SetIsInBed(bool a_Flag)
- {
- m_bIsInBed = a_Flag;
- if (!a_Flag)
- {
- GetWorld()->BroadcastEntityAnimation(*this, 2);
- }
- }
+ /** Sets a player's in-bed state.
+ We can't be sure plugins will keep this value updated, so no exporting.
+ If value is false (not in bed), will update players of the fact that they have been ejected from the bed. */
+ void SetIsInBed(bool a_IsInBed);
/** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */
void StartEating(void);
@@ -377,7 +415,7 @@ public:
void Respawn(void); // tolua_export
void SetVisible( bool a_bVisible); // tolua_export
- bool IsVisible(void) const { return m_bVisible; } // tolua_export
+ bool IsVisible(void) const { return m_IsVisible; } // tolua_export
/** Saves all player data, such as inventory, to JSON. */
void SaveToDisk(void);
@@ -450,14 +488,17 @@ public:
/** Sets the flying relative maximum speed. Sends the update to player, if needed. */
void SetFlyingMaxSpeed(double a_Speed);
- /** Sets the crouch status, broadcasts to all visible players */
- void SetCrouch(bool a_IsCrouched);
+ /** Starts or stops crouching, if our current body stance permits, broadcasting the state change. */
+ void SetCrouch(bool a_ShouldCrouch);
- /** Starts or stops sprinting, sends the max speed update to the client, if needed */
- void SetSprint(bool a_IsSprinting);
+ /** Starts or stops elytra flight, if our current body stance permits, broadcasting the state change. */
+ void SetElytraFlight(bool a_ShouldElytraFly);
- /** Flags the player as flying */
- void SetFlying(bool a_IsFlying);
+ /** Starts or stops flying, broadcasting the state change. */
+ void SetFlying(bool a_ShouldFly);
+
+ /** Starts or stops sprinting, if our current body stance permits, broadcasting the state change. */
+ void SetSprint(bool a_ShouldSprint);
/** If true the player can fly even when he's not in creative. */
void SetCanFly(bool a_CanFly);
@@ -501,7 +542,7 @@ public:
// tolua_begin
/** Returns wheter the player can fly or not. */
- virtual bool CanFly(void) const { return m_CanFly; }
+ virtual bool CanFly(void) const { return m_IsFlightCapable; }
/** (Re)loads the rank and permissions from the cRankManager.
Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */
@@ -541,14 +582,6 @@ public:
*/
void NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved);
- // cEntity overrides:
- virtual bool IsCrouched (void) const override { return m_IsCrouched; }
- virtual bool IsSprinting(void) const override { return m_IsSprinting; }
- virtual bool IsRclking (void) const override { return IsEating() || IsChargingBow(); }
-
- virtual void AttachTo(cEntity * a_AttachTo) override;
- virtual void Detach(void) override;
-
/** Returns the progress mined per tick for the block a_Block as a fraction
(1 would be completely mined)
Depends on hardness values so check those are correct.
@@ -565,18 +598,38 @@ public:
If the item is already known, does nothing. */
void AddKnownItem(const cItem & a_Item);
+ /** Update a player's size, for example, on body stance changes. */
+ void SetSize(float a_Width, float a_Height);
+
// cEntity overrides:
+ virtual void AttachTo(cEntity * a_AttachTo) override;
+ virtual void Detach(void) override;
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); }
virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); }
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
virtual cItem GetOffHandEquipedItem(void) const override { return m_Inventory.GetShieldSlot(); }
+ virtual bool IsCrouched(void) const override;
+ virtual bool IsElytraFlying(void) const override;
+ virtual bool IsOnGround(void) const override { return m_bTouchGround; }
+ virtual bool IsSprinting(void) const override;
private:
+ /** Xp Level stuff */
+ enum
+ {
+ XP_TO_LEVEL15 = 255,
+ XP_PER_LEVEL_TO15 = 17,
+ XP_TO_LEVEL30 = 825
+ } ;
+
typedef std::vector<std::vector<AString> > AStringVectorVector;
+ /** The current body stance the player has adopted. */
+ std::variant<BodyStanceCrouching, BodyStanceSleeping, BodyStanceSprinting, BodyStanceStanding, BodyStanceGliding> m_BodyStance;
+
/** The name of the rank assigned to this player. */
AString m_Rank;
@@ -599,16 +652,6 @@ private:
AString m_MsgPrefix, m_MsgSuffix;
AString m_MsgNameColorCode;
- /** Xp Level stuff */
- enum
- {
- XP_TO_LEVEL15 = 255,
- XP_PER_LEVEL_TO15 = 17,
- XP_TO_LEVEL30 = 825
- } ;
-
- bool m_bVisible;
-
// Food-related variables:
/** Represents the food bar, one point equals half a "drumstick" */
int m_FoodLevel;
@@ -622,8 +665,6 @@ private:
/** 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_Stance;
-
/** Stores the player's inventory, consisting of crafting grid, hotbar, and main slots */
cInventory m_Inventory;
@@ -656,12 +697,6 @@ private:
cSlotNums m_InventoryPaintSlots;
- /** If true, we are locking m_Position to m_FrozenPosition. */
- bool m_IsFrozen;
-
- /** Was the player frozen manually by a plugin or automatically by the server? */
- bool m_IsManuallyFrozen;
-
/** Max speed, relative to the game default.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1. */
@@ -677,12 +712,25 @@ private:
Default value is 1. */
double m_FlyingMaxSpeed;
- bool m_IsCrouched;
- bool m_IsSprinting;
- bool m_IsFlying;
+ bool m_IsChargingBow;
bool m_IsFishing;
- bool m_CanFly; // If this is true the player can fly. Even if he is not in creative.
+ /** If this is true the player can fly. Even if he is not in creative. */
+ bool m_IsFlightCapable;
+
+ bool m_IsFlying;
+
+ /** If true, we are locking m_Position to m_FrozenPosition. */
+ bool m_IsFrozen;
+
+ /** Was the player frozen manually by a plugin or automatically by the server? */
+ bool m_IsManuallyFrozen;
+
+ /** Flag used by food handling system to determine whether a teleport has just happened.
+ Will not apply food penalties if found to be true; will set to false after processing. */
+ bool m_IsTeleporting;
+
+ bool m_IsVisible;
/** The world tick in which eating will be finished. -1 if not eating */
Int64 m_EatingFinishTick;
@@ -692,8 +740,7 @@ private:
int m_CurrentXp;
unsigned int m_EnchantmentSeed;
- bool m_IsChargingBow;
- int m_BowCharge;
+ int m_BowCharge;
UInt32 m_FloaterID;
@@ -701,19 +748,10 @@ private:
cStatManager m_Stats;
- /** Flag representing whether the player is currently in a bed
- Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
- bool m_bIsInBed;
-
/** How long till the player's inventory will be saved
Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */
unsigned int m_TicksUntilNextSave;
- /** Flag used by food handling system to determine whether a teleport has just happened
- Will not apply food penalties if found to be true; will set to false after processing
- */
- bool m_bIsTeleporting;
-
AString m_CustomName;
/** Displayed skin part bit mask */
@@ -769,6 +807,7 @@ private:
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
virtual float GetEnchantmentBlastKnockbackReduction() override;
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
+ virtual bool IsRclking(void) const override { return IsEating() || IsChargingBow(); }
virtual void OnAddToWorld(cWorld & a_World) override;
virtual void OnRemoveFromWorld(cWorld & a_World) override;
virtual void SpawnOn(cClientHandle & a_Client) override;