diff options
Diffstat (limited to 'src/Entities')
-rw-r--r-- | src/Entities/Entity.cpp | 47 | ||||
-rw-r--r-- | src/Entities/Entity.h | 26 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 7 | ||||
-rw-r--r-- | src/Entities/Player.h | 2 |
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); |