summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Entity.cpp47
-rw-r--r--src/Entities/Entity.h26
-rw-r--r--src/Entities/Player.cpp7
-rw-r--r--src/Entities/Player.h2
4 files changed, 63 insertions, 19 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 91eb0744a..108f79e82 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -13,6 +13,7 @@
#include "Player.h"
#include "Items/ItemHandler.h"
#include "../FastRandom.h"
+#include "../NetherPortalScanner.h"
@@ -42,6 +43,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
m_WorldTravellingFrom(nullptr),
m_EntityType(a_EntityType),
m_World(nullptr),
+ m_IsWorldChangeScheduled(false),
m_IsFireproof(false),
m_TicksSinceLastBurnDamage(0),
m_TicksSinceLastLavaDamage(0),
@@ -1260,9 +1262,26 @@ void cEntity::DetectCacti(void)
+void cEntity::ScheduleMoveToWorld(cWorld * a_World, Vector3d a_NewPosition)
+{
+ m_NewWorld = a_World;
+ m_NewWorldPosition = a_NewPosition;
+ m_IsWorldChangeScheduled = true;
+}
+
+
+
bool cEntity::DetectPortal()
{
+ // If somebody scheduled a world change with ScheduleMoveToWorld, change worlds now.
+ if (m_IsWorldChangeScheduled)
+ {
+ m_IsWorldChangeScheduled = false;
+ MoveToWorld(m_NewWorld, false, m_NewWorldPosition);
+ return true;
+ }
+
if (GetWorld()->GetDimension() == dimOverworld)
{
if (GetWorld()->GetLinkedNetherWorldName().empty() && GetWorld()->GetLinkedEndWorldName().empty())
@@ -1312,8 +1331,15 @@ bool cEntity::DetectPortal()
// Send a respawn packet before world is loaded / generated so the client isn't left in limbo
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld);
}
-
- return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
+
+ Vector3d TargetPos = GetPosition();
+ TargetPos.x *= 8.0;
+ TargetPos.z *= 8.0;
+
+ cWorld * TargetWorld = cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName(), dimNether, GetWorld()->GetName());
+ LOGD("Jumping nether -> overworld");
+ new cNetherPortalScanner(this, TargetWorld, TargetPos, 256);
+ return false;
}
else
{
@@ -1329,8 +1355,15 @@ bool cEntity::DetectPortal()
((cPlayer *)this)->AwardAchievement(achEnterPortal);
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether);
}
-
- return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedNetherWorldName(), dimNether, GetWorld()->GetName()), false);
+
+ Vector3d TargetPos = GetPosition();
+ TargetPos.x /= 8.0;
+ TargetPos.z /= 8.0;
+
+ cWorld * TargetWorld = cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedNetherWorldName(), dimNether, GetWorld()->GetName());
+ LOGD("Jumping overworld -> nether");
+ new cNetherPortalScanner(this, TargetWorld, TargetPos, 128);
+ return false;
}
}
case E_BLOCK_END_PORTAL:
@@ -1392,7 +1425,7 @@ bool cEntity::DetectPortal()
-bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
+bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition)
{
UNUSED(a_ShouldSendRespawn);
ASSERT(a_World != nullptr);
@@ -1414,6 +1447,8 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
SetWorldTravellingFrom(GetWorld()); // cChunk::Tick() handles entity removal
GetWorld()->BroadcastDestroyEntity(*this);
+ SetPosition(a_NewPosition);
+
// Queue add to new world
a_World->AddEntity(this);
cWorld * OldWorld = cRoot::Get()->GetWorld(GetWorld()->GetName()); // Required for the hook HOOK_ENTITY_CHANGED_WORLD
@@ -1438,7 +1473,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn)
return false;
}
- return DoMoveToWorld(World, a_ShouldSendRespawn);
+ return DoMoveToWorld(World, a_ShouldSendRespawn, GetPosition());
}
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 58d1287e7..8d1d62ddf 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -392,15 +392,20 @@ public:
/// Teleports to the coordinates specified
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ);
+ /// Schedules a MoveToWorld call to occur on the next Tick of the entity
+ void ScheduleMoveToWorld(cWorld * a_World, Vector3d a_NewPosition);
+
+ bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) { return DoMoveToWorld(a_World, a_ShouldSendRespawn, a_NewPosition); }
+
/** Moves entity to specified world, taking a world pointer */
- bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) { return DoMoveToWorld(a_World, a_ShouldSendRespawn); }
+ bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) { return MoveToWorld(a_World, a_ShouldSendRespawn, GetPosition()); }
/** Moves entity to specified world, taking a world name */
bool MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn = true);
// tolua_end
- virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn);
+ virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition);
/** Returns if the entity is travelling away from a specified world */
bool IsWorldTravellingFrom(cWorld * a_World) const { return (m_WorldTravellingFrom == a_World); }
@@ -530,23 +535,28 @@ protected:
eEntityType m_EntityType;
cWorld * m_World;
+
+ /** State variables for ScheduleMoveToWorld. */
+ bool m_IsWorldChangeScheduled;
+ cWorld * m_NewWorld;
+ Vector3d m_NewWorldPosition;
- /// Whether the entity is capable of taking fire or lava damage.
+ /** Whether the entity is capable of taking fire or lava damage. */
bool m_IsFireproof;
- /// Time, in ticks, since the last damage dealt by being on fire. Valid only if on fire (IsOnFire())
+ /** Time, in ticks, since the last damage dealt by being on fire. Valid only if on fire (IsOnFire()) */
int m_TicksSinceLastBurnDamage;
- /// Time, in ticks, since the last damage dealt by standing in lava. Reset to zero when moving out of lava.
+ /** Time, in ticks, since the last damage dealt by standing in lava. Reset to zero when moving out of lava. */
int m_TicksSinceLastLavaDamage;
- /// Time, in ticks, since the last damage dealt by standing in fire. Reset to zero when moving out of fire.
+ /** Time, in ticks, since the last damage dealt by standing in fire. Reset to zero when moving out of fire. */
int m_TicksSinceLastFireDamage;
- /// Time, in ticks, until the entity extinguishes its fire
+ /** Time, in ticks, until the entity extinguishes its fire */
int m_TicksLeftBurning;
- /// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
+ /** Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. */
int m_TicksSinceLastVoidDamage;
/** Does the actual speed-setting. The default implementation just sets the member variable value;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index e3e3fac4f..0ca560d75 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1620,10 +1620,7 @@ void cPlayer::TossItems(const cItems & a_Items)
}
-
-
-
-bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
+bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition)
{
ASSERT(a_World != nullptr);
@@ -1653,6 +1650,8 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal
GetWorld()->RemovePlayer(this, false);
+ SetPosition(a_NewPosition);
+
// Queue adding player to the new world, including all the necessary adjustments to the object
a_World->AddPlayer(this);
cWorld * OldWorld = cRoot::Get()->GetWorld(GetWorld()->GetName()); // Required for the hook HOOK_ENTITY_CHANGED_WORLD
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 799990bf2..dffb61677 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -358,7 +358,7 @@ public:
/** Moves the player to the specified world.
Returns true if successful, false on failure (world not found). */
- virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) override;
+ virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) override;
/** Saves all player data, such as inventory, to JSON */
bool SaveToDisk(void);