summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Entities/Entity.cpp29
-rw-r--r--src/Entities/Entity.h9
-rw-r--r--src/Entities/Player.cpp39
-rw-r--r--src/Entities/Player.h7
4 files changed, 72 insertions, 12 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 0bb8b97bc..b6a67859b 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -134,6 +134,15 @@ bool cEntity::Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld)
+void cEntity::OnAcquireSpectator(cPlayer & a_Player)
+{
+ m_Spectators.push_back(&a_Player);
+}
+
+
+
+
+
void cEntity::OnAddToWorld(cWorld & a_World)
{
// Spawn the entity on the clients:
@@ -146,6 +155,19 @@ void cEntity::OnAddToWorld(cWorld & a_World)
+void cEntity::OnLoseSpectator(cPlayer & a_Player)
+{
+ const auto Spectator = std::find(m_Spectators.begin(), m_Spectators.end(), &a_Player);
+
+ ASSERT(Spectator != m_Spectators.end());
+ std::swap(*Spectator, m_Spectators.back());
+ m_Spectators.pop_back();
+}
+
+
+
+
+
void cEntity::OnRemoveFromWorld(cWorld & a_World)
{
// Remove all mobs from the leashed list of mobs:
@@ -154,6 +176,13 @@ void cEntity::OnRemoveFromWorld(cWorld & a_World)
m_LeashedMobs.front()->Unleash(false, true);
}
+ for (const auto Player : m_Spectators)
+ {
+ Player->OnLoseSpectated();
+ }
+
+ m_Spectators.clear();
+
if (m_AttachedTo != nullptr)
{
Detach();
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 941d07339..2f9ba229b 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -135,11 +135,17 @@ public:
Adds the entity to the world. */
bool Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld);
+ /** Called when a player begins spectating this entity. */
+ void OnAcquireSpectator(cPlayer & a_Player);
+
/** Called when the entity is added to a world.
e.g after first spawning or after successfuly moving between worlds.
\param a_World The world being added to. */
virtual void OnAddToWorld(cWorld & a_World);
+ /** Called when a player stops spectating this entity. */
+ void OnLoseSpectator(cPlayer & a_Player);
+
/** Called when the entity is removed from a world.
e.g. When the entity is destroyed or moved to a different world.
\param a_World The world being removed from. */
@@ -723,4 +729,7 @@ private:
/** List of leashed mobs to this entity */
cMonsterList m_LeashedMobs;
+
+ /** List of players who are spectating this entity. */
+ std::vector<cPlayer *> m_Spectators;
} ; // tolua_export
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());
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index e0a88814d..2f2b9d62e 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -93,6 +93,9 @@ public:
cPlayer(const std::shared_ptr<cClientHandle> & a_Client);
virtual ~cPlayer() override;
+ /** Called when spectation stops, because the player crouched or when the entity we're spectating gets removed from the world. */
+ void OnLoseSpectated();
+
// tolua_begin
/** Sets the experience total
@@ -184,7 +187,7 @@ public:
void SendRotation(double a_YawDegrees, double a_PitchDegrees);
/** Spectates the target entity. If a_Target is nullptr or a pointer to self, end spectation. */
- void SpectateEntity(const cEntity * a_Target);
+ void SpectateEntity(cEntity * a_Target);
/** Returns the position where projectiles thrown by this player should start, player eye position + adjustment */
Vector3d GetThrowStartPos(void) const;
@@ -731,7 +734,7 @@ private:
cTeam * m_Team;
/** The entity that this player is spectating, nullptr if none. */
- const cEntity * m_Spectating;
+ cEntity * m_Spectating;
StatisticsManager m_Stats;