summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/ArrowEntity.cpp13
-rw-r--r--src/Entities/Entity.cpp18
-rw-r--r--src/Entities/HangingEntity.cpp55
-rw-r--r--src/Entities/HangingEntity.h86
-rw-r--r--src/Entities/ItemFrame.cpp11
-rw-r--r--src/Entities/ItemFrame.h1
-rw-r--r--src/Entities/Minecart.cpp1
-rw-r--r--src/Entities/Painting.cpp18
-rw-r--r--src/Entities/Painting.h18
-rw-r--r--src/Entities/Player.cpp27
-rw-r--r--src/Entities/Player.h14
-rw-r--r--src/Entities/ProjectileEntity.cpp7
12 files changed, 136 insertions, 133 deletions
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index 0fbbfb681..3c1fabb1b 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -72,14 +72,8 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
- if (GetSpeed().EqualsEps(Vector3d(0, 0, 0), 0.0000001))
- {
- SetSpeed(GetLookVector().NormalizeCopy() * 0.1); // Ensure that no division by zero happens later
- }
-
Vector3d Hit = a_HitPos;
- Vector3d SinkMovement = (GetSpeed() / 1000);
- Hit += SinkMovement * (0.0005 / SinkMovement.Length()); // Make arrow sink into block a centimetre so it lodges (but not to far so it goes black clientside)
+ Hit += GetSpeed().NormalizeCopy() / 100000; // Make arrow sink into block a bit so it lodges (TODO: investigate how to stop them going so far so that they become black clientside)
super::OnHitSolidBlock(Hit, a_HitFace);
Vector3i BlockHit = Hit.Floor();
@@ -195,11 +189,6 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
if (m_IsInGround)
{
- // When an arrow hits, the client doesn't think its in the ground and keeps on moving, IF BroadcastMovementUpdate() and TeleportEntity was called during flight, AT ALL
- // Fix is to simply not sync with the client and send a teleport to confirm pos after arrow has stabilised (around 1 sec after landing)
- // We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
- // Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position
-
if (!m_HasTeleported) // Sent a teleport already, don't do again
{
if (m_HitGroundTimer > std::chrono::milliseconds(500))
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 07cfb97b2..039c58ee4 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1263,7 +1263,7 @@ bool cEntity::DetectPortal()
{
if (GetWorld()->GetDimension() == dimOverworld)
{
- if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty())
+ if (GetWorld()->GetLinkedNetherWorldName().empty() && GetWorld()->GetLinkedEndWorldName().empty())
{
// Teleportation to either dimension not enabled, don't bother proceeding
return false;
@@ -1314,7 +1314,7 @@ bool cEntity::DetectPortal()
}
else
{
- if (GetWorld()->GetNetherWorldName().empty())
+ if (GetWorld()->GetLinkedNetherWorldName().empty())
{
return false;
}
@@ -1327,7 +1327,7 @@ bool cEntity::DetectPortal()
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether);
}
- return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false);
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedNetherWorldName(), dimNether, GetWorld()->GetName()), false);
}
}
case E_BLOCK_END_PORTAL:
@@ -1358,7 +1358,7 @@ bool cEntity::DetectPortal()
}
else
{
- if (GetWorld()->GetEndWorldName().empty())
+ if (GetWorld()->GetLinkedEndWorldName().empty())
{
return false;
}
@@ -1371,7 +1371,7 @@ bool cEntity::DetectPortal()
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd);
}
- return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false);
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedEndWorldName(), dimEnd, GetWorld()->GetName()), false);
}
}
@@ -1632,8 +1632,12 @@ void cEntity::TeleportToEntity(cEntity & a_Entity)
void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
{
- SetPosition(a_PosX, a_PosY, a_PosZ);
- m_World->BroadcastTeleportEntity(*this);
+ // ask the plugins to allow teleport to the new position.
+ if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPos, Vector3d(a_PosX, a_PosY, a_PosZ)))
+ {
+ SetPosition(a_PosX, a_PosY, a_PosZ);
+ m_World->BroadcastTeleportEntity(*this);
+ }
}
diff --git a/src/Entities/HangingEntity.cpp b/src/Entities/HangingEntity.cpp
index a6b9c40c8..a37d8702e 100644
--- a/src/Entities/HangingEntity.cpp
+++ b/src/Entities/HangingEntity.cpp
@@ -11,7 +11,7 @@
cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_Facing, double a_X, double a_Y, double a_Z) :
cEntity(a_EntityType, a_X, a_Y, a_Z, 0.8, 0.8),
- m_Facing(a_Facing)
+ m_Facing(cHangingEntity::BlockFaceToProtocolFace(a_Facing))
{
SetMaxHealth(1);
SetHealth(1);
@@ -21,60 +21,9 @@ cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_Facing, do
-void cHangingEntity::SetFacing(eBlockFace a_Facing)
-{
- // Y-based faces are not allowed:
- switch (a_Facing)
- {
- case BLOCK_FACE_NONE:
- case BLOCK_FACE_YM:
- case BLOCK_FACE_YP:
- {
- LOGWARNING("%s: Invalid facing: %d. Ignoring.", __FUNCTION__, a_Facing);
- ASSERT(!"Tried to set a bad facing!");
- return;
- }
- default: break;
- }
-
- m_Facing = a_Facing;
-}
-
-
-
-
-
void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle)
{
- int Dir = 0;
-
- // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
- switch (m_Facing)
- {
- case BLOCK_FACE_ZP: Dir = 0; break;
- case BLOCK_FACE_ZM: Dir = 2; break;
- case BLOCK_FACE_XM: Dir = 1; break;
- case BLOCK_FACE_XP: Dir = 3; break;
- default:
- {
- LOGINFO("Invalid facing (%d) in a cHangingEntity at {%d, %d, %d}, adjusting to BLOCK_FACE_XP.",
- m_Facing, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ()
- );
- Dir = 3;
- }
- }
-
- if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
- {
- SetYaw((Dir * 90) - 180);
- }
- else
- {
- SetYaw(Dir * 90);
- }
-
- a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch());
- a_ClientHandle.SendEntityMetadata(*this);
+ SetYaw(GetProtocolFacing() * 90);
}
diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h
index d1ef79a68..507502ac6 100644
--- a/src/Entities/HangingEntity.h
+++ b/src/Entities/HangingEntity.h
@@ -24,28 +24,82 @@ public:
// tolua_begin
/** Returns the direction in which the entity is facing. */
- eBlockFace GetFacing() const { return m_Facing; }
-
+ eBlockFace GetFacing() const { return cHangingEntity::ProtocolFaceToBlockFace(m_Facing); }
+
/** Set the direction in which the entity is facing. */
- void SetFacing(eBlockFace a_Facing);
-
- /** Returns the X coord of the block in which the entity resides. */
- int GetBlockX() const { return POSX_TOINT; }
-
- /** Returns the Y coord of the block in which the entity resides. */
- int GetBlockY() const { return POSY_TOINT; }
-
- /** Returns the Z coord of the block in which the entity resides. */
- int GetBlockZ() const { return POSZ_TOINT; }
+ void SetFacing(eBlockFace a_Facing) { m_Facing = cHangingEntity::BlockFaceToProtocolFace(a_Facing); }
// tolua_end
-private:
+ /** Returns the direction in which the entity is facing. */
+ Byte GetProtocolFacing() const { return m_Facing; }
- virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
- virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override {}
+ /** Set the direction in which the entity is facing. */
+ void SetProtocolFacing(Byte a_Facing)
+ {
+ ASSERT((a_Facing <= 3) && (a_Facing >= 0));
+ m_Facing = a_Facing;
+ }
- eBlockFace m_Facing;
+protected:
+
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
+ virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override
+ {
+ UNUSED(a_Dt);
+ UNUSED(a_Chunk);
+ }
+
+ /** Converts protocol hanging item facing to eBlockFace values */
+ inline static eBlockFace ProtocolFaceToBlockFace(Byte a_ProtocolFace)
+ {
+ eBlockFace Dir;
+
+ // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
+ switch (a_ProtocolFace)
+ {
+ case 0: Dir = BLOCK_FACE_ZP; break;
+ case 2: Dir = BLOCK_FACE_ZM; break;
+ case 1: Dir = BLOCK_FACE_XM; break;
+ case 3: Dir = BLOCK_FACE_XP; break;
+ default:
+ {
+ LOGINFO("Invalid facing (%d) in a cHangingEntity, adjusting to BLOCK_FACE_XP.", a_ProtocolFace);
+ ASSERT(!"Tried to convert a bad facing!");
+
+ Dir = cHangingEntity::ProtocolFaceToBlockFace(3);
+ }
+ }
+
+ return Dir;
+ }
+
+ /** Converts eBlockFace values to protocol hanging item faces */
+ inline static Byte BlockFaceToProtocolFace(eBlockFace a_BlockFace)
+ {
+ Byte Dir;
+
+ // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
+ switch (a_BlockFace)
+ {
+ case BLOCK_FACE_ZP: Dir = 0; break;
+ case BLOCK_FACE_ZM: Dir = 2; break;
+ case BLOCK_FACE_XM: Dir = 1; break;
+ case BLOCK_FACE_XP: Dir = 3; break;
+ default:
+ {
+ // Uncomment when entities are initialised with their real data, instead of dummy values:
+ // LOGINFO("Invalid facing (%d) in a cHangingEntity, adjusting to BLOCK_FACE_XP.", a_BlockFace);
+ // ASSERT(!"Tried to convert a bad facing!");
+
+ Dir = cHangingEntity::BlockFaceToProtocolFace(BLOCK_FACE_XP);
+ }
+ }
+
+ return Dir;
+ }
+
+ Byte m_Facing;
}; // tolua_export
diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp
index dfffcd3ed..4e6e38f1f 100644
--- a/src/Entities/ItemFrame.cpp
+++ b/src/Entities/ItemFrame.cpp
@@ -92,3 +92,14 @@ void cItemFrame::GetDrops(cItems & a_Items, cEntity * a_Killer)
+
+void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle)
+{
+ super::SpawnOn(a_ClientHandle);
+ a_ClientHandle.SendSpawnObject(*this, 71, GetProtocolFacing(), (Byte)GetYaw(), (Byte)GetPitch());
+ a_ClientHandle.SendEntityMetadata(*this);
+}
+
+
+
+
diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h
index ced8c37af..2444b26a3 100644
--- a/src/Entities/ItemFrame.h
+++ b/src/Entities/ItemFrame.h
@@ -42,6 +42,7 @@ private:
virtual void OnRightClicked(cPlayer & a_Player) override;
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
cItem m_Item;
Byte m_ItemRotation;
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index 776f957f4..a32926838 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -11,6 +11,7 @@
#include "../Chunk.h"
#include "Player.h"
#include "../BoundingBox.h"
+#include "../UI/MinecartWithChestWindow.h"
#define NO_SPEED 0.0
#define MAX_SPEED 8
diff --git a/src/Entities/Painting.cpp b/src/Entities/Painting.cpp
index 6f6277f28..02a8f6ed0 100644
--- a/src/Entities/Painting.cpp
+++ b/src/Entities/Painting.cpp
@@ -10,10 +10,9 @@
-cPainting::cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z)
- : cEntity(etPainting, a_X, a_Y, a_Z, 1, 1),
- m_Name(a_Name),
- m_Direction(a_Direction)
+cPainting::cPainting(const AString & a_Name, eBlockFace a_Direction, double a_X, double a_Y, double a_Z)
+ : cHangingEntity(etPainting, a_Direction, a_X, a_Y, a_Z),
+ m_Name(a_Name)
{
}
@@ -24,6 +23,7 @@ cPainting::cPainting(const AString & a_Name, int a_Direction, double a_X, double
void cPainting::SpawnOn(cClientHandle & a_Client)
{
+ super::SpawnOn(a_Client);
a_Client.SendPaintingSpawn(*this);
}
@@ -31,16 +31,6 @@ void cPainting::SpawnOn(cClientHandle & a_Client)
-void cPainting::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
-{
- UNUSED(a_Dt);
- UNUSED(a_Chunk);
-}
-
-
-
-
-
void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer)
{
if ((a_Killer != nullptr) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative())
diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h
index 6e8a382fc..20968d4f0 100644
--- a/src/Entities/Painting.h
+++ b/src/Entities/Painting.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Entity.h"
+#include "HangingEntity.h"
@@ -9,9 +9,9 @@
// tolua_begin
class cPainting :
- public cEntity
+ public cHangingEntity
{
- typedef cEntity super;
+ typedef cHangingEntity super;
public:
@@ -19,19 +19,14 @@ public:
CLASS_PROTODEF(cPainting)
- cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z);
+ cPainting(const AString & a_Name, eBlockFace a_Direction, double a_X, double a_Y, double a_Z);
- // tolua_begin
-
- const AString & GetName(void) const { return m_Name; }
- int GetDirection(void) const { return m_Direction; }
-
- // tolua_end
+ /** Returns the protocol name of the painting */
+ const AString & GetName(void) const { return m_Name; } // tolua_export
private:
virtual void SpawnOn(cClientHandle & a_Client) override;
- virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
virtual void KilledBy(TakeDamageInfo & a_TDI) override
{
@@ -40,7 +35,6 @@ private:
}
AString m_Name;
- int m_Direction;
}; // tolua_export
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index e1d9f4550..c89e7b87c 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -5,7 +5,7 @@
#include <unordered_map>
#include "../ChatColor.h"
#include "../Server.h"
-#include "../UI/Window.h"
+#include "../UI/InventoryWindow.h"
#include "../UI/WindowOwner.h"
#include "../World.h"
#include "../Bindings/PluginManager.h"
@@ -232,7 +232,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
}
bool CanMove = true;
- if (!GetPosition().EqualsEps(m_LastPos, 0.01)) // Non negligible change in position from last tick?
+ if (!GetPosition().EqualsEps(m_LastPos, 0.02)) // Non negligible change in position from last tick? 0.02 tp prevent continous calling while floating sometimes.
{
// Apply food exhaustion from movement:
ApplyFoodExhaustionFromMovement();
@@ -396,6 +396,7 @@ int cPlayer::DeltaExperience(int a_Xp_delta)
// Make sure they didn't subtract too much
m_CurrentXp = std::max(m_CurrentXp, 0);
+
// Update total for score calculation
if (a_Xp_delta > 0)
{
@@ -1274,13 +1275,17 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach)
void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
{
- SetPosition(a_PosX, a_PosY, a_PosZ);
- m_LastGroundHeight = static_cast<float>(a_PosY);
- m_LastJumpHeight = static_cast<float>(a_PosY);
- m_bIsTeleporting = true;
+ // ask plugins to allow teleport to the new position.
+ if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPos, Vector3d(a_PosX, a_PosY, a_PosZ)))
+ {
+ SetPosition(a_PosX, a_PosY, a_PosZ);
+ m_LastGroundHeight = static_cast<float>(a_PosY);
+ m_LastJumpHeight = static_cast<float>(a_PosY);
+ m_bIsTeleporting = true;
- m_World->BroadcastTeleportEntity(*this, GetClientHandle());
- m_ClientHandle->SendPlayerMoveLook();
+ m_World->BroadcastTeleportEntity(*this, GetClientHandle());
+ m_ClientHandle->SendPlayerMoveLook();
+ }
}
@@ -1725,9 +1730,9 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
m_FoodTickTimer = root.get("foodTickTimer", 0).asInt();
m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
- m_LifetimeTotalXp = root.get("xpTotal", 0).asInt();
- m_CurrentXp = root.get("xpCurrent", 0).asInt();
- m_IsFlying = root.get("isflying", 0).asBool();
+ m_LifetimeTotalXp = root.get("xpTotal", 0).asInt();
+ m_CurrentXp = root.get("xpCurrent", 0).asInt();
+ m_IsFlying = root.get("isflying", 0).asBool();
m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt();
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index e02c66bd3..3dae58dc1 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -314,8 +314,18 @@ public:
// tolua_end
- /** Sets a player's in-bed state; we can't be sure plugins will keep this value updated, so no exporting */
- void SetIsInBed(bool a_Flag) { m_bIsInBed = a_Flag; }
+ /** Sets a player's in-bed state
+ We can't be sure plugins will keep this value updated, so no exporting
+ If value is false (not in bed), will update players of the fact that they have been ejected from the bed
+ */
+ void SetIsInBed(bool a_Flag)
+ {
+ m_bIsInBed = a_Flag;
+ if (!a_Flag)
+ {
+ GetWorld()->BroadcastEntityAnimation(*this, 2);
+ }
+ }
/** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */
void StartEating(void);
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 4f20bfae6..21ec4e63a 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -334,12 +334,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
void cProjectileEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
-
- // TODO: see BroadcastMovementUpdate; RelativeMove packet jerkiness affects projectiles too (cause of sympton described in cArrowEntity::Tick())
- if (GetProjectileKind() != pkArrow)
- {
- BroadcastMovementUpdate();
- }
+ BroadcastMovementUpdate();
}