1
0

Freeze player until chunk is loaded

This commit is contained in:
Safwat Halaby
2015-12-24 12:37:32 +02:00
parent c4c839bee1
commit 400f875918
3 changed files with 116 additions and 1 deletions

View File

@@ -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;
}
@@ -1263,6 +1292,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 +1602,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);