From cb640ffea4a51a10db2e379ada8dc0487378ba09 Mon Sep 17 00:00:00 2001 From: bibo38 Date: Wed, 12 Oct 2016 14:38:45 +0200 Subject: Spectators added (#2852) --- src/Entities/Entity.h | 2 +- src/Entities/ExpOrb.cpp | 2 +- src/Entities/Minecart.cpp | 10 +++++- src/Entities/Pawn.cpp | 6 +++- src/Entities/Pickup.cpp | 6 ++++ src/Entities/Player.cpp | 69 +++++++++++++++++++++++++++++++++++++++ src/Entities/Player.h | 4 +++ src/Entities/ProjectileEntity.cpp | 10 +++++- 8 files changed, 104 insertions(+), 5 deletions(-) (limited to 'src/Entities') diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index c543fd9c1..4833f8b5c 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -429,7 +429,7 @@ public: cEntity * GetAttached(); /** Attaches to the specified entity; detaches from any previous one first */ - void AttachTo(cEntity * a_AttachTo); + virtual void AttachTo(cEntity * a_AttachTo); /** Detaches from the currently attached entity, if any */ virtual void Detach(void); diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp index f51bbb300..290f9e665 100644 --- a/src/Entities/ExpOrb.cpp +++ b/src/Entities/ExpOrb.cpp @@ -45,7 +45,7 @@ void cExpOrb::SpawnOn(cClientHandle & a_Client) void cExpOrb::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { cPlayer * a_ClosestPlayer(m_World->FindClosestPlayer(Vector3f(GetPosition()), 5)); - if (a_ClosestPlayer != nullptr) + if ((a_ClosestPlayer != nullptr) && (!a_ClosestPlayer->IsGameModeSpectator())) { Vector3f a_PlayerPos(a_ClosestPlayer->GetPosition()); a_PlayerPos.y++; diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 43291bdc8..88b5959d5 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -39,7 +39,15 @@ public: { ASSERT(a_Entity != nullptr); - if (!a_Entity->IsPlayer() && !a_Entity->IsMob() && !a_Entity->IsMinecart() && !a_Entity->IsBoat()) + if ( + ( + !a_Entity->IsPlayer() || + reinterpret_cast(a_Entity)->IsGameModeSpectator() // Spectators doesn't collide with anything + ) && + !a_Entity->IsMob() && + !a_Entity->IsMinecart() && + !a_Entity->IsBoat() + ) { return false; } diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp index dbcaba591..4b42dbb57 100644 --- a/src/Entities/Pawn.cpp +++ b/src/Entities/Pawn.cpp @@ -108,7 +108,11 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) } } Callback(this); - m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), Callback); + // Spectators cannot push entities around + if ((!IsPlayer()) || (!reinterpret_cast(this)->IsGameModeSpectator())) + { + m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), Callback); + } super::Tick(a_Dt, a_Chunk); if (!IsTicking()) diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp index 12d535f84..b1892e4cc 100644 --- a/src/Entities/Pickup.cpp +++ b/src/Entities/Pickup.cpp @@ -208,6 +208,12 @@ bool cPickup::CollectedBy(cPlayer & a_Dest) return false; // Not old enough } + // If the player is a spectator, he cannot collect anything + if (a_Dest.IsGameModeSpectator()) + { + return false; + } + if (cRoot::Get()->GetPluginManager()->CallHookCollectingPickup(a_Dest, *this)) { // LOG("Pickup %d cannot be collected by \"%s\", because a plugin has said no.", m_UniqueID, a_Dest->GetName().c_str()); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 5ab5e4567..db4b07553 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -250,6 +250,20 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) m_Stats.AddValue(statMinutesPlayed, 1); + // Handle the player detach, when the player is in spectator mode + if ( + (IsGameModeSpectator()) && + (m_AttachedTo != nullptr) && + ( + (m_AttachedTo->IsDestroyed()) || // Watching entity destruction + (m_AttachedTo->GetHealth() <= 0) || // Watching entity dead + (IsCrouched()) // Or the player wants to be detached + ) + ) + { + Detach(); + } + // Handle a frozen player TickFreezeCode(); if (m_IsFrozen) @@ -1233,6 +1247,16 @@ bool cPlayer::IsGameModeSpectator(void) const + +bool cPlayer::CanMobsTarget(void) const +{ + return IsGameModeSurvival() || IsGameModeAdventure(); +} + + + + + void cPlayer::SetTeam(cTeam * a_Team) { if (m_Team == a_Team) @@ -1344,6 +1368,12 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) return; } + // Detach, if the player is switching from or to the spectator mode + if ((m_GameMode == gmSpectator) || (a_GameMode == gmSpectator)) + { + Detach(); + } + m_GameMode = a_GameMode; m_ClientHandle->SendGameMode(a_GameMode); @@ -1379,6 +1409,13 @@ void cPlayer::SetCapabilities() { SetVisible(false); SetCanFly(true); + + // Clear the current dragging item of the player + if (GetWindow() != nullptr) + { + m_DraggingItem.Empty(); + GetClientHandle()->SendInventorySlot(-1, -1, m_DraggingItem); + } } else { @@ -2476,8 +2513,40 @@ bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks) +void cPlayer::AttachTo(cEntity * a_AttachTo) +{ + // Different attach, if this is a spectator + if (IsGameModeSpectator()) + { + m_AttachedTo = a_AttachTo; + GetClientHandle()->SendCameraSetTo(*m_AttachedTo); + return; + } + + super::AttachTo(a_AttachTo); +} + + + + + void cPlayer::Detach() { + if (m_AttachedTo == nullptr) + { + // The player is not attached to anything. Bail out. + return; + } + + // Different detach, if this is a spectator + if (IsGameModeSpectator()) + { + GetClientHandle()->SendCameraSetTo(*this); + TeleportToEntity(*m_AttachedTo); + m_AttachedTo = nullptr; + return; + } + super::Detach(); int PosX = POSX_TOINT; int PosY = POSY_TOINT; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 25796ee50..04cb5232b 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -193,6 +193,9 @@ public: /** Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current world */ bool IsGameModeSpectator(void) const; + /** Returns true if the player can be targeted by Mobs */ + bool CanMobsTarget(void) const; + AString GetIP(void) const { return m_IP; } // tolua_export /** Returns the associated team, nullptr if none */ @@ -518,6 +521,7 @@ public: virtual bool IsSprinting(void) const override { return m_IsSprinting; } virtual bool IsRclking (void) const override { return IsEating() || IsChargingBow(); } + virtual void AttachTo(cEntity * a_AttachTo) override; virtual void Detach(void) override; /** Called by cClientHandle when the client is being destroyed. diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index fb7da85a1..3bded2b56 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -167,7 +167,15 @@ public: return false; } - if (!a_Entity->IsMob() && !a_Entity->IsMinecart() && !a_Entity->IsPlayer() && !a_Entity->IsBoat()) + if ( + !a_Entity->IsMob() && + !a_Entity->IsMinecart() && + ( + !a_Entity->IsPlayer() || + static_cast(a_Entity)->IsGameModeSpectator() + ) && + !a_Entity->IsBoat() + ) { // Not an entity that interacts with a projectile return false; -- cgit v1.2.3