From 4b60d55d8d97da113dbb2e90c2a4834e8e813629 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 7 Feb 2022 00:53:44 +0000 Subject: Spectation: keep track of spectators + Keep a list of spectators so that pointer clean-up can happen when the spectated is killed. * Fix invalid game state when riding/spectating and then entering or leaving spectator mode. --- src/Entities/Player.cpp | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'src/Entities/Player.cpp') diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 30650a6d0..3fd2aac48 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -170,6 +170,17 @@ cPlayer::~cPlayer(void) +void cPlayer::OnLoseSpectated() +{ + m_ClientHandle->SendCameraSetTo(*this); + m_ClientHandle->SendPlayerMoveLook(); + m_Spectating = nullptr; +} + + + + + int cPlayer::CalcLevelFromXp(int a_XpTotal) { // level 0 to 15 @@ -1304,18 +1315,23 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) if (m_GameMode == a_GameMode) { - // Gamemode already set + // New gamemode unchanged, we're done: return; } - // Detach, if the player is switching from or to the spectator mode - if ((m_GameMode == gmSpectator) || (a_GameMode == gmSpectator)) + m_GameMode = a_GameMode; + UpdateCapabilities(); + + if (IsGameModeSpectator()) { + // Spectators cannot ride entities: Detach(); } - - m_GameMode = a_GameMode; - UpdateCapabilities(); + else + { + // Non-spectators may not spectate: + SpectateEntity(nullptr); + } m_ClientHandle->SendGameMode(a_GameMode); m_ClientHandle->SendInventorySlot(-1, -1, m_DraggingItem); @@ -1452,7 +1468,7 @@ void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees) -void cPlayer::SpectateEntity(const cEntity * a_Target) +void cPlayer::SpectateEntity(cEntity * a_Target) { if (a_Target == this) { @@ -1468,13 +1484,13 @@ void cPlayer::SpectateEntity(const cEntity * a_Target) if (a_Target == nullptr) { - m_ClientHandle->SendCameraSetTo(*this); - m_ClientHandle->SendPlayerMoveLook(); - m_Spectating = nullptr; + m_Spectating->OnLoseSpectator(*this); + OnLoseSpectated(); return; } m_Spectating = a_Target; + a_Target->OnAcquireSpectator(*this); m_ClientHandle->SendCameraSetTo(*a_Target); } @@ -3055,6 +3071,9 @@ void cPlayer::OnRemoveFromWorld(cWorld & a_World) // Remove any references to this player pointer by windows in the old world: CloseWindow(false); + // Stop spectation and remove our reference from the spectated: + SpectateEntity(nullptr); + // Remove the client handle from the world: m_World->RemoveClientFromChunks(m_ClientHandle.get()); -- cgit v1.2.3