summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Entity.h2
-rw-r--r--src/Entities/ExpOrb.cpp2
-rw-r--r--src/Entities/Minecart.cpp10
-rw-r--r--src/Entities/Pawn.cpp6
-rw-r--r--src/Entities/Pickup.cpp6
-rw-r--r--src/Entities/Player.cpp69
-rw-r--r--src/Entities/Player.h4
-rw-r--r--src/Entities/ProjectileEntity.cpp10
8 files changed, 104 insertions, 5 deletions
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<cPlayer *>(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<cPlayer *>(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<cPlayer *>(a_Entity)->IsGameModeSpectator()
+ ) &&
+ !a_Entity->IsBoat()
+ )
{
// Not an entity that interacts with a projectile
return false;