Merge pull request #3124 from LogicParrot/noFall2
Improve Player freeze code
This commit is contained in:
commit
a6b0c74f79
@ -1946,7 +1946,6 @@ a_Player:OpenWindow(Window);
|
|||||||
GetFoodPoisonedTicksRemaining = { Params = "", Return = "", Notes = "Returns the number of ticks left for the food posoning effect" },
|
GetFoodPoisonedTicksRemaining = { Params = "", Return = "", Notes = "Returns the number of ticks left for the food posoning effect" },
|
||||||
GetFoodSaturationLevel = { Params = "", Return = "number", Notes = "Returns the food saturation (overcharge of the food level, is depleted before food level)" },
|
GetFoodSaturationLevel = { Params = "", Return = "number", Notes = "Returns the food saturation (overcharge of the food level, is depleted before food level)" },
|
||||||
GetFoodTickTimer = { Params = "", Return = "", Notes = "Returns the number of ticks past the last food-based heal or damage action; when this timer reaches 80, a new heal / damage is applied." },
|
GetFoodTickTimer = { Params = "", Return = "", Notes = "Returns the number of ticks past the last food-based heal or damage action; when this timer reaches 80, a new heal / damage is applied." },
|
||||||
GetFrozenDuration = { Params = "", Return = "number", Notes = "Returns the number of ticks since the player was frozen" },
|
|
||||||
GetGameMode = { Return = "{{Globals#GameMode|GameMode}}", Notes = "Returns the player's gamemode. The player may have their gamemode unassigned, in which case they inherit the gamemode from the current {{cWorld|world}}.<br /> <b>NOTE:</b> Instead of comparing the value returned by this function to the gmXXX constants, use the IsGameModeXXX() functions. These functions handle the gamemode inheritance automatically."},
|
GetGameMode = { Return = "{{Globals#GameMode|GameMode}}", Notes = "Returns the player's gamemode. The player may have their gamemode unassigned, in which case they inherit the gamemode from the current {{cWorld|world}}.<br /> <b>NOTE:</b> Instead of comparing the value returned by this function to the gmXXX constants, use the IsGameModeXXX() functions. These functions handle the gamemode inheritance automatically."},
|
||||||
GetIP = { Return = "string", Notes = "Returns the IP address of the player, if available. Returns an empty string if there's no IP to report."},
|
GetIP = { Return = "string", Notes = "Returns the IP address of the player, if available. Returns an empty string if there's no IP to report."},
|
||||||
GetInventory = { Return = "{{cInventory|Inventory}}", Notes = "Returns the player's inventory"},
|
GetInventory = { Return = "{{cInventory|Inventory}}", Notes = "Returns the player's inventory"},
|
||||||
|
@ -604,7 +604,19 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
|||||||
|
|
||||||
void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
m_IsInTick = true;
|
// If we are not valid, tick players and bailout
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
for (auto Entity : m_Entities)
|
||||||
|
{
|
||||||
|
if (Entity->IsPlayer())
|
||||||
|
{
|
||||||
|
Entity->Tick(a_Dt, *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BroadcastPendingBlockChanges();
|
BroadcastPendingBlockChanges();
|
||||||
|
|
||||||
CheckBlocks();
|
CheckBlocks();
|
||||||
@ -668,7 +680,6 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
|||||||
} // for itr - m_Entitites[]
|
} // for itr - m_Entitites[]
|
||||||
|
|
||||||
ApplyWeatherToTop();
|
ApplyWeatherToTop();
|
||||||
m_IsInTick = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -502,7 +502,6 @@ private:
|
|||||||
|
|
||||||
/** If the chunk fails to load, should it be queued in the generator or reset back to invalid? */
|
/** If the chunk fails to load, should it be queued in the generator or reset back to invalid? */
|
||||||
bool m_ShouldGenerateIfLoadFailed;
|
bool m_ShouldGenerateIfLoadFailed;
|
||||||
bool m_IsInTick; // True if the chunk is executing the tick() method.
|
|
||||||
bool m_IsLightValid; // True if the blocklight and skylight are calculated
|
bool m_IsLightValid; // True if the blocklight and skylight are calculated
|
||||||
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
||||||
bool m_IsSaving; // True if the chunk is being saved
|
bool m_IsSaving; // True if the chunk is being saved
|
||||||
|
@ -2920,8 +2920,9 @@ void cChunkMap::cChunkLayer::Tick(std::chrono::milliseconds a_Dt)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||||
{
|
{
|
||||||
// Only tick chunks that are valid and should be ticked:
|
// Only tick chunks that should be ticked:
|
||||||
if ((m_Chunks[i] != nullptr) && m_Chunks[i]->IsValid() && m_Chunks[i]->ShouldBeTicked())
|
// Note that chunks that are not IsValid() will only tick players and then bailout
|
||||||
|
if ((m_Chunks[i] != nullptr) && m_Chunks[i]->ShouldBeTicked())
|
||||||
{
|
{
|
||||||
m_Chunks[i]->Tick(a_Dt);
|
m_Chunks[i]->Tick(a_Dt);
|
||||||
}
|
}
|
||||||
|
@ -764,6 +764,12 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_Player->IsFrozen())
|
||||||
|
{
|
||||||
|
// Ignore client-side updates if the player is frozen
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3d NewPosition(a_PosX, a_PosY, a_PosZ);
|
Vector3d NewPosition(a_PosX, a_PosY, a_PosZ);
|
||||||
Vector3d OldPosition = GetPlayer()->GetPosition();
|
Vector3d OldPosition = GetPlayer()->GetPosition();
|
||||||
auto PreviousIsOnGround = GetPlayer()->IsOnGround();
|
auto PreviousIsOnGround = GetPlayer()->IsOnGround();
|
||||||
@ -1864,8 +1870,6 @@ void cClientHandle::RemoveFromWorld(void)
|
|||||||
// Here, we set last streamed values to bogus ones so everything is resent
|
// Here, we set last streamed values to bogus ones so everything is resent
|
||||||
m_LastStreamedChunkX = 0x7fffffff;
|
m_LastStreamedChunkX = 0x7fffffff;
|
||||||
m_LastStreamedChunkZ = 0x7fffffff;
|
m_LastStreamedChunkZ = 0x7fffffff;
|
||||||
|
|
||||||
m_HasSentPlayerChunk = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1884,6 +1888,15 @@ void cClientHandle::InvalidateCachedSentChunk()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cClientHandle::IsPlayerChunkSent()
|
||||||
|
{
|
||||||
|
return m_HasSentPlayerChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cClientHandle::CheckBlockInteractionsRate(void)
|
bool cClientHandle::CheckBlockInteractionsRate(void)
|
||||||
{
|
{
|
||||||
ASSERT(m_Player != nullptr);
|
ASSERT(m_Player != nullptr);
|
||||||
@ -1943,8 +1956,9 @@ void cClientHandle::Tick(float a_Dt)
|
|||||||
|
|
||||||
|
|
||||||
// Freeze the player if it is standing on a chunk not yet sent to the client
|
// Freeze the player if it is standing on a chunk not yet sent to the client
|
||||||
|
m_HasSentPlayerChunk = false;
|
||||||
|
if (m_Player->GetParentChunk() != nullptr)
|
||||||
{
|
{
|
||||||
bool PlayerIsStandingAtASentChunk = false;
|
|
||||||
// If the chunk is invalid, do not bother checking if it's sent to the client, it is definitely not
|
// If the chunk is invalid, do not bother checking if it's sent to the client, it is definitely not
|
||||||
if (m_Player->GetParentChunk()->IsValid())
|
if (m_Player->GetParentChunk()->IsValid())
|
||||||
{
|
{
|
||||||
@ -1952,7 +1966,7 @@ void cClientHandle::Tick(float a_Dt)
|
|||||||
// If so, the chunk has been sent to the client. This is an optimization that saves an iteration of m_SentChunks.
|
// If so, the chunk has been sent to the client. This is an optimization that saves an iteration of m_SentChunks.
|
||||||
if (cChunkCoords(m_Player->GetChunkX(), m_Player->GetChunkZ()) == m_CachedSentChunk)
|
if (cChunkCoords(m_Player->GetChunkX(), m_Player->GetChunkZ()) == m_CachedSentChunk)
|
||||||
{
|
{
|
||||||
PlayerIsStandingAtASentChunk = true;
|
m_HasSentPlayerChunk = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1963,12 +1977,10 @@ void cClientHandle::Tick(float a_Dt)
|
|||||||
if (itr != m_SentChunks.end())
|
if (itr != m_SentChunks.end())
|
||||||
{
|
{
|
||||||
m_CachedSentChunk = *itr;
|
m_CachedSentChunk = *itr;
|
||||||
PlayerIsStandingAtASentChunk = true;
|
m_HasSentPlayerChunk = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The player will freeze itself if it is standing on a chunk not yet sent to the client
|
|
||||||
m_Player->TickFreezeCode(PlayerIsStandingAtASentChunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the chunk the player's in was just sent, spawn the player:
|
// If the chunk the player's in was just sent, spawn the player:
|
||||||
@ -2281,15 +2293,6 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
|
|||||||
cCSLock Lock(m_CSChunkLists);
|
cCSLock Lock(m_CSChunkLists);
|
||||||
m_SentChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
|
m_SentChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it is the chunk the player's in, make them spawn (in the tick thread):
|
|
||||||
if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
|
|
||||||
{
|
|
||||||
if ((a_ChunkX == m_Player->GetChunkX()) && (a_ChunkZ == m_Player->GetChunkZ()))
|
|
||||||
{
|
|
||||||
m_HasSentPlayerChunk = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -365,6 +365,8 @@ public: // tolua_export
|
|||||||
|
|
||||||
void InvalidateCachedSentChunk();
|
void InvalidateCachedSentChunk();
|
||||||
|
|
||||||
|
bool IsPlayerChunkSent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class cServer; // Needs access to SetSelf()
|
friend class cServer; // Needs access to SetSelf()
|
||||||
|
@ -65,7 +65,6 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
|
|||||||
m_GameMode(eGameMode_NotSet),
|
m_GameMode(eGameMode_NotSet),
|
||||||
m_IP(""),
|
m_IP(""),
|
||||||
m_ClientHandle(a_Client),
|
m_ClientHandle(a_Client),
|
||||||
m_FreezeCounter(-1),
|
|
||||||
m_NormalMaxSpeed(1.0),
|
m_NormalMaxSpeed(1.0),
|
||||||
m_SprintingMaxSpeed(1.3),
|
m_SprintingMaxSpeed(1.3),
|
||||||
m_FlyingMaxSpeed(1.0),
|
m_FlyingMaxSpeed(1.0),
|
||||||
@ -119,7 +118,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
|
|||||||
|
|
||||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
m_LastGroundHeight = static_cast<float>(GetPosY());
|
||||||
m_Stance = GetPosY() + 1.62;
|
m_Stance = GetPosY() + 1.62;
|
||||||
FreezeInternal(GetPosition(), false); // Freeze. Will be unfrozen once the chunk is loaded
|
|
||||||
|
|
||||||
if (m_GameMode == gmNotSet)
|
if (m_GameMode == gmNotSet)
|
||||||
{
|
{
|
||||||
@ -246,13 +245,16 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
ASSERT(!"Player ticked whilst in the process of destruction!");
|
ASSERT(!"Player ticked whilst in the process of destruction!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_Stats.AddValue(statMinutesPlayed, 1);
|
m_Stats.AddValue(statMinutesPlayed, 1);
|
||||||
|
|
||||||
// Handle a frozen player
|
// Handle a frozen player
|
||||||
|
TickFreezeCode();
|
||||||
if (m_IsFrozen)
|
if (m_IsFrozen)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ASSERT((GetParentChunk() != nullptr) && (GetParentChunk()->IsValid()));
|
||||||
|
|
||||||
ASSERT(a_Chunk.IsValid());
|
ASSERT(a_Chunk.IsValid());
|
||||||
|
|
||||||
@ -314,18 +316,13 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::TickFreezeCode(bool a_MyChunkIsSent)
|
void cPlayer::TickFreezeCode()
|
||||||
{
|
{
|
||||||
// This function is ticked by the player's client handle. This ensures it always ticks, even if the player
|
|
||||||
// is standing in an unloaded chunk, unlike cPlayer::Tick. We need this because the freeze handling code must
|
|
||||||
// also tick in unloaded chunks.
|
|
||||||
if (m_IsFrozen)
|
if (m_IsFrozen)
|
||||||
{
|
{
|
||||||
m_FreezeCounter += 1;
|
if ((!m_IsManuallyFrozen) && (GetClientHandle()->IsPlayerChunkSent()))
|
||||||
if ((!m_IsManuallyFrozen) && (a_MyChunkIsSent))
|
|
||||||
{
|
{
|
||||||
cWorld::cLock Lock(*GetWorld());
|
// If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded and sent
|
||||||
// If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded
|
|
||||||
Unfreeze();
|
Unfreeze();
|
||||||
|
|
||||||
// Pull the player out of any solids that might have loaded on them.
|
// Pull the player out of any solids that might have loaded on them.
|
||||||
@ -357,26 +354,16 @@ void cPlayer::TickFreezeCode(bool a_MyChunkIsSent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (GetWorld()->GetWorldAge() % 4096 == 0)
|
||||||
{
|
{
|
||||||
// If the player was externally / manually frozen (plugin, etc.) or if the chunk isn't loaded yet:
|
// Despite the client side freeze, the player may be able to move a little by
|
||||||
// 1. Set the location to m_FrozenPosition every tick.
|
// Jumping or canceling flight. Re-freeze every now and then
|
||||||
// 2. Zero out the speed every tick.
|
FreezeInternal(GetPosition(), m_IsManuallyFrozen);
|
||||||
// 3. Send location updates every 60 ticks.
|
|
||||||
|
|
||||||
if ((m_FreezeCounter % 60 == 0) || ((m_FrozenPosition - GetPosition()).SqrLength() > 2 * 2))
|
|
||||||
{
|
|
||||||
SetPosition(m_FrozenPosition);
|
|
||||||
SetSpeed(0, 0, 0);
|
|
||||||
BroadcastMovementUpdate(m_ClientHandle.get());
|
|
||||||
m_ClientHandle->SendPlayerPosition();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!a_MyChunkIsSent)
|
if (!GetClientHandle()->IsPlayerChunkSent())
|
||||||
{
|
{
|
||||||
FreezeInternal(GetPosition(), false);
|
FreezeInternal(GetPosition(), false);
|
||||||
}
|
}
|
||||||
@ -772,8 +759,9 @@ double cPlayer::GetMaxSpeed(void) const
|
|||||||
void cPlayer::SetNormalMaxSpeed(double a_Speed)
|
void cPlayer::SetNormalMaxSpeed(double a_Speed)
|
||||||
{
|
{
|
||||||
m_NormalMaxSpeed = a_Speed;
|
m_NormalMaxSpeed = a_Speed;
|
||||||
if (!m_IsSprinting && !m_IsFlying)
|
if (!m_IsSprinting && !m_IsFlying && !m_IsFrozen)
|
||||||
{
|
{
|
||||||
|
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||||
m_ClientHandle->SendPlayerMaxSpeed();
|
m_ClientHandle->SendPlayerMaxSpeed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -785,8 +773,9 @@ void cPlayer::SetNormalMaxSpeed(double a_Speed)
|
|||||||
void cPlayer::SetSprintingMaxSpeed(double a_Speed)
|
void cPlayer::SetSprintingMaxSpeed(double a_Speed)
|
||||||
{
|
{
|
||||||
m_SprintingMaxSpeed = a_Speed;
|
m_SprintingMaxSpeed = a_Speed;
|
||||||
if (m_IsSprinting && !m_IsFlying)
|
if (m_IsSprinting && !m_IsFlying && !m_IsFrozen)
|
||||||
{
|
{
|
||||||
|
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||||
m_ClientHandle->SendPlayerMaxSpeed();
|
m_ClientHandle->SendPlayerMaxSpeed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -800,7 +789,11 @@ void cPlayer::SetFlyingMaxSpeed(double a_Speed)
|
|||||||
m_FlyingMaxSpeed = a_Speed;
|
m_FlyingMaxSpeed = a_Speed;
|
||||||
|
|
||||||
// Update the flying speed, always:
|
// Update the flying speed, always:
|
||||||
m_ClientHandle->SendPlayerAbilities();
|
if (!m_IsFrozen)
|
||||||
|
{
|
||||||
|
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||||
|
m_ClientHandle->SendPlayerAbilities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -907,7 +900,11 @@ void cPlayer::SetFlying(bool a_IsFlying)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_IsFlying = a_IsFlying;
|
m_IsFlying = a_IsFlying;
|
||||||
m_ClientHandle->SendPlayerAbilities();
|
if (!m_IsFrozen)
|
||||||
|
{
|
||||||
|
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||||
|
m_ClientHandle->SendPlayerAbilities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1471,22 +1468,14 @@ bool cPlayer::IsFrozen()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cPlayer::GetFrozenDuration()
|
|
||||||
{
|
|
||||||
return m_FreezeCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::Unfreeze()
|
void cPlayer::Unfreeze()
|
||||||
{
|
{
|
||||||
m_FreezeCounter = -1;
|
GetClientHandle()->SendPlayerAbilities();
|
||||||
|
GetClientHandle()->SendPlayerMaxSpeed();
|
||||||
|
|
||||||
m_IsFrozen = false;
|
m_IsFrozen = false;
|
||||||
SetPosition(m_FrozenPosition);
|
BroadcastMovementUpdate(GetClientHandle());
|
||||||
BroadcastMovementUpdate(m_ClientHandle.get());
|
GetClientHandle()->SendPlayerPosition();
|
||||||
m_ClientHandle->SendPlayerPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1545,8 +1534,12 @@ void cPlayer::ForceSetSpeed(const Vector3d & a_Speed)
|
|||||||
|
|
||||||
void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
||||||
{
|
{
|
||||||
|
if (m_IsFrozen)
|
||||||
|
{
|
||||||
|
// Do not set speed to a frozen client
|
||||||
|
return;
|
||||||
|
}
|
||||||
super::DoSetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ);
|
super::DoSetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ);
|
||||||
|
|
||||||
// Send the speed to the client so he actualy moves
|
// Send the speed to the client so he actualy moves
|
||||||
m_ClientHandle->SendEntityVelocity(*this);
|
m_ClientHandle->SendEntityVelocity(*this);
|
||||||
}
|
}
|
||||||
@ -1768,9 +1761,33 @@ void cPlayer::TossItems(const cItems & a_Items)
|
|||||||
|
|
||||||
void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen)
|
void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen)
|
||||||
{
|
{
|
||||||
|
SetSpeed(0, 0, 0);
|
||||||
|
SetPosition(a_Location);
|
||||||
m_IsFrozen = true;
|
m_IsFrozen = true;
|
||||||
m_FrozenPosition = a_Location;
|
|
||||||
m_IsManuallyFrozen = a_ManuallyFrozen;
|
m_IsManuallyFrozen = a_ManuallyFrozen;
|
||||||
|
|
||||||
|
double NormalMaxSpeed = GetNormalMaxSpeed();
|
||||||
|
double SprintMaxSpeed = GetSprintingMaxSpeed();
|
||||||
|
double FlyingMaxpeed = GetFlyingMaxSpeed();
|
||||||
|
bool IsFlying = m_IsFlying;
|
||||||
|
|
||||||
|
// Set the client-side speed to 0
|
||||||
|
m_NormalMaxSpeed = 0;
|
||||||
|
m_SprintingMaxSpeed = 0;
|
||||||
|
m_FlyingMaxSpeed = 0;
|
||||||
|
m_IsFlying = true;
|
||||||
|
|
||||||
|
// Send the client its fake speed and max speed of 0
|
||||||
|
GetClientHandle()->SendPlayerMoveLook();
|
||||||
|
GetClientHandle()->SendPlayerAbilities();
|
||||||
|
GetClientHandle()->SendPlayerMaxSpeed();
|
||||||
|
GetClientHandle()->SendEntityVelocity(*this);
|
||||||
|
|
||||||
|
// Keep the server side speed variables as they were in the first place
|
||||||
|
m_NormalMaxSpeed = NormalMaxSpeed;
|
||||||
|
m_SprintingMaxSpeed = SprintMaxSpeed;
|
||||||
|
m_FlyingMaxSpeed = FlyingMaxpeed;
|
||||||
|
m_IsFlying = IsFlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
void TickFreezeCode(bool a_MyChunkIsSent);
|
void TickFreezeCode();
|
||||||
|
|
||||||
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
|
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
|
||||||
|
|
||||||
@ -148,9 +148,6 @@ public:
|
|||||||
/** Is the player frozen? */
|
/** Is the player frozen? */
|
||||||
bool IsFrozen();
|
bool IsFrozen();
|
||||||
|
|
||||||
/** How long has the player been frozen? */
|
|
||||||
int GetFrozenDuration();
|
|
||||||
|
|
||||||
/** Cancels Freeze(...) and allows the player to move naturally. */
|
/** Cancels Freeze(...) and allows the player to move naturally. */
|
||||||
void Unfreeze();
|
void Unfreeze();
|
||||||
|
|
||||||
@ -605,15 +602,9 @@ protected:
|
|||||||
|
|
||||||
cSlotNums m_InventoryPaintSlots;
|
cSlotNums m_InventoryPaintSlots;
|
||||||
|
|
||||||
/** if m_IsFrozen is true, we lock m_Location to this position. */
|
|
||||||
Vector3d m_FrozenPosition;
|
|
||||||
|
|
||||||
/** If true, we are locking m_Position to m_FrozenPosition. */
|
/** If true, we are locking m_Position to m_FrozenPosition. */
|
||||||
bool m_IsFrozen;
|
bool m_IsFrozen;
|
||||||
|
|
||||||
/** */
|
|
||||||
int m_FreezeCounter;
|
|
||||||
|
|
||||||
/** Was the player frozen manually by a plugin or automatically by the server? */
|
/** Was the player frozen manually by a plugin or automatically by the server? */
|
||||||
bool m_IsManuallyFrozen;
|
bool m_IsManuallyFrozen;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user