diff options
Diffstat (limited to 'src/Entities/Player.cpp')
-rw-r--r-- | src/Entities/Player.cpp | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 33ded6ab9..80f07cb65 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -63,6 +63,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) : m_GameMode(eGameMode_NotSet), m_IP(""), m_ClientHandle(a_Client), + m_FreezeCounter(-1), m_NormalMaxSpeed(1.0), m_SprintingMaxSpeed(1.3), m_FlyingMaxSpeed(1.0), @@ -112,6 +113,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) : m_LastGroundHeight = static_cast<float>(GetPosY()); m_Stance = GetPosY() + 1.62; + FreezeInternal(GetPosition(), false); // Freeze. Will be unfrozen once the chunk is loaded if (m_GameMode == gmNotSet) { @@ -220,8 +222,35 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) m_Stats.AddValue(statMinutesPlayed, 1); + // Handle a frozen player + if (m_IsFrozen) + { + m_FreezeCounter += 1; + if (!m_IsManuallyFrozen && a_Chunk.IsValid()) + { + // If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded + Unfreeze(); + } + else + { + // If the player was externally / manually frozen (plugin, etc.) or if the chunk isn't loaded yet: + // 1. Set the location to m_FrozenPosition every tick. + // 2. Zero out the speed every tick. + // 3. Send location updates every 60 ticks. + SetPosition(m_FrozenPosition); + SetSpeed(0, 0, 0); + if (m_FreezeCounter % 60 == 0) + { + BroadcastMovementUpdate(m_ClientHandle.get()); + m_ClientHandle->SendPlayerPosition(); + } + return; + } + } + if (!a_Chunk.IsValid()) { + FreezeInternal(GetPosition(), false); // This may happen if the cPlayer is created before the chunks have the chance of being loaded / generated (#83) return; } @@ -879,7 +908,15 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI) case dtEnderPearl: DamageText = "misused an ender pearl"; break; case dtAdmin: DamageText = "was administrator'd"; break; case dtExplosion: DamageText = "blew up"; break; - default: DamageText = "died, somehow; we've no idea how though"; break; + case dtAttack: DamageText = "was attacked by thin air"; break; + #ifndef __clang__ + default: + { + ASSERT(!"Unknown damage type"); + DamageText = "died, somehow; we've no idea how though"; + break; + } + #endif // __clang__ } AString DeathMessage = Printf("%s %s", GetName().c_str(), DamageText.c_str()); PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); @@ -1263,6 +1300,46 @@ void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) +void cPlayer::Freeze(const Vector3d & a_Location) +{ + FreezeInternal(a_Location, true); +} + + + + + +bool cPlayer::IsFrozen() +{ + return m_IsFrozen; +} + + + + + +int cPlayer::GetFrozenDuration() +{ + return m_FreezeCounter; +} + + + + + +void cPlayer::Unfreeze() +{ + m_FreezeCounter = -1; + m_IsFrozen = false; + SetPosition(m_FrozenPosition); + BroadcastMovementUpdate(m_ClientHandle.get()); + m_ClientHandle->SendPlayerPosition(); +} + + + + + void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees) { SetYaw(a_YawDegrees); @@ -1533,6 +1610,20 @@ void cPlayer::TossItems(const cItems & a_Items) } + + + +void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen) +{ + m_IsFrozen = true; + m_FrozenPosition = a_Location; + m_IsManuallyFrozen = a_ManuallyFrozen; +} + + + + + bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) { ASSERT(a_World != nullptr); |