summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/ArrowEntity.cpp5
-rw-r--r--src/Entities/Boat.cpp5
-rw-r--r--src/Entities/Entity.cpp47
-rw-r--r--src/Entities/FireworkEntity.cpp5
-rw-r--r--src/Entities/Minecart.cpp5
-rw-r--r--src/Entities/Pawn.cpp6
-rw-r--r--src/Entities/Pickup.cpp5
-rw-r--r--src/Entities/Player.cpp88
-rw-r--r--src/Entities/Player.h3
-rw-r--r--src/Entities/ProjectileEntity.cpp5
-rw-r--r--src/Entities/TNTEntity.cpp5
11 files changed, 133 insertions, 46 deletions
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index 59d742f8d..366592549 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -180,6 +180,11 @@ void cArrowEntity::CollectedBy(cPlayer & a_Dest)
void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
m_Timer += a_Dt;
if (m_bIsCollected)
diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp
index 330e54740..f9b83eee5 100644
--- a/src/Entities/Boat.cpp
+++ b/src/Entities/Boat.cpp
@@ -102,6 +102,11 @@ void cBoat::OnRightClicked(cPlayer & a_Player)
void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
BroadcastMovementUpdate();
SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 2adbc3142..b2fa56143 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1433,19 +1433,22 @@ bool cEntity::DetectPortal()
}
m_PortalCooldownData.m_TicksDelayed = 0;
+ // Nether portal in the nether
if (GetWorld()->GetDimension() == dimNether)
{
if (GetWorld()->GetLinkedOverworldName().empty())
{
return false;
}
+ cWorld * DestinationWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedOverworldName());
+ eDimension DestionationDim = DestinationWorld->GetDimension();
m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn
if (IsPlayer())
{
// Send a respawn packet before world is loaded / generated so the client isn't left in limbo
- (reinterpret_cast<cPlayer *>(this))->GetClientHandle()->SendRespawn(dimOverworld);
+ (reinterpret_cast<cPlayer *>(this))->GetClientHandle()->SendRespawn(DestionationDim);
}
Vector3d TargetPos = GetPosition();
@@ -1454,23 +1457,30 @@ bool cEntity::DetectPortal()
cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedOverworldName());
ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start()
- LOGD("Jumping nether -> overworld");
+ LOGD("Jumping %s -> %s", DimensionToString(dimNether).c_str(), DimensionToString(DestionationDim).c_str());
new cNetherPortalScanner(this, TargetWorld, TargetPos, 256);
return true;
}
+ // Nether portal in the overworld
else
{
if (GetWorld()->GetLinkedNetherWorldName().empty())
{
return false;
}
+ cWorld * DestinationWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedNetherWorldName());
+ eDimension DestionationDim = DestinationWorld->GetDimension();
m_PortalCooldownData.m_ShouldPreventTeleportation = true;
if (IsPlayer())
{
- reinterpret_cast<cPlayer *>(this)->AwardAchievement(achEnterPortal);
- reinterpret_cast<cPlayer *>(this)->GetClientHandle()->SendRespawn(dimNether);
+ if (DestionationDim == dimNether)
+ {
+ reinterpret_cast<cPlayer *>(this)->AwardAchievement(achEnterPortal);
+ }
+
+ reinterpret_cast<cPlayer *>(this)->GetClientHandle()->SendRespawn(DestionationDim);
}
Vector3d TargetPos = GetPosition();
@@ -1479,7 +1489,7 @@ bool cEntity::DetectPortal()
cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedNetherWorldName());
ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start()
- LOGD("Jumping overworld -> nether");
+ LOGD("Jumping %s -> %s", DimensionToString(dimOverworld).c_str(), DimensionToString(DestionationDim).c_str());
new cNetherPortalScanner(this, TargetWorld, TargetPos, 128);
return true;
}
@@ -1491,6 +1501,7 @@ bool cEntity::DetectPortal()
return false;
}
+ // End portal in the end
if (GetWorld()->GetDimension() == dimEnd)
{
@@ -1498,37 +1509,55 @@ bool cEntity::DetectPortal()
{
return false;
}
+ cWorld * DestinationWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedOverworldName());
+ eDimension DestionationDim = DestinationWorld->GetDimension();
+
m_PortalCooldownData.m_ShouldPreventTeleportation = true;
if (IsPlayer())
{
cPlayer * Player = reinterpret_cast<cPlayer *>(this);
- Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z);
- Player->GetClientHandle()->SendRespawn(dimOverworld);
+ if (Player->GetBedWorld() == DestinationWorld)
+ {
+ Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z);
+ }
+ else
+ {
+ Player->TeleportToCoords(DestinationWorld->GetSpawnX(), DestinationWorld->GetSpawnY(), DestinationWorld->GetSpawnZ());
+ }
+ Player->GetClientHandle()->SendRespawn(DestionationDim);
}
cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedOverworldName());
ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start()
+ LOGD("Jumping %s -> %s", DimensionToString(dimEnd).c_str(), DimensionToString(DestionationDim).c_str());
return MoveToWorld(TargetWorld, false);
}
+ // End portal in the overworld
else
{
if (GetWorld()->GetLinkedEndWorldName().empty())
{
return false;
}
+ cWorld * DestinationWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedEndWorldName());
+ eDimension DestionationDim = DestinationWorld->GetDimension();
m_PortalCooldownData.m_ShouldPreventTeleportation = true;
if (IsPlayer())
{
- reinterpret_cast<cPlayer *>(this)->AwardAchievement(achEnterTheEnd);
- reinterpret_cast<cPlayer *>(this)->GetClientHandle()->SendRespawn(dimEnd);
+ if (DestionationDim == dimEnd)
+ {
+ reinterpret_cast<cPlayer *>(this)->AwardAchievement(achEnterTheEnd);
+ }
+ reinterpret_cast<cPlayer *>(this)->GetClientHandle()->SendRespawn(DestionationDim);
}
cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedEndWorldName());
ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start()
+ LOGD("Jumping %s -> %s", DimensionToString(dimOverworld).c_str(), DimensionToString(DestionationDim).c_str());
return MoveToWorld(TargetWorld, false);
}
diff --git a/src/Entities/FireworkEntity.cpp b/src/Entities/FireworkEntity.cpp
index 552549b7c..b0ba4e6c5 100644
--- a/src/Entities/FireworkEntity.cpp
+++ b/src/Entities/FireworkEntity.cpp
@@ -65,6 +65,11 @@ void cFireworkEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_C
void cFireworkEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
if (m_TicksToExplosion <= 0)
{
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index 3b58a1ef9..43291bdc8 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -1264,6 +1264,11 @@ void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
void cMinecartWithFurnace::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
if (m_IsFueled)
{
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index 04425dd51..dbcaba591 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -111,7 +111,11 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), Callback);
super::Tick(a_Dt, a_Chunk);
-
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
HandleFalling();
}
diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp
index 69bb981e6..12d535f84 100644
--- a/src/Entities/Pickup.cpp
+++ b/src/Entities/Pickup.cpp
@@ -116,6 +116,11 @@ void cPickup::SpawnOn(cClientHandle & a_Client)
void cPickup::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
BroadcastMovementUpdate(); // Notify clients of position
m_Timer += a_Dt;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 50bec3608..889aef778 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -893,6 +893,15 @@ void cPlayer::SetBedPos(const Vector3i & a_Pos, cWorld * a_World)
+cWorld * cPlayer::GetBedWorld()
+{
+ return m_SpawnWorld;
+}
+
+
+
+
+
void cPlayer::SetFlying(bool a_IsFlying)
{
if (a_IsFlying == m_IsFlying)
@@ -1771,64 +1780,71 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d
return false;
}
- // Ask the plugins if the player is allowed to changing the world
+ // Ask the plugins if the player is allowed to change the world
if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World))
{
- // A Plugin doesn't allow the player to changing the world
+ // A Plugin doesn't allow the player to change the world
return false;
}
- // The clienthandle caches the coords of the chunk we're standing at. Invalidate this.
- GetClientHandle()->InvalidateCachedSentChunk();
+ GetWorld()->QueueTask([this, a_World, a_ShouldSendRespawn, a_NewPosition](cWorld & a_OldWorld)
+ {
+ // The clienthandle caches the coords of the chunk we're standing at. Invalidate this.
+ GetClientHandle()->InvalidateCachedSentChunk();
- // Prevent further ticking in this world
- SetIsTicking(false);
+ // Prevent further ticking in this world
+ SetIsTicking(false);
- // Tell others we are gone
- GetWorld()->BroadcastDestroyEntity(*this);
+ // Tell others we are gone
+ GetWorld()->BroadcastDestroyEntity(*this);
- // Remove player from world
- GetWorld()->RemovePlayer(this, false);
+ // Remove player from world
+ GetWorld()->RemovePlayer(this, false);
- // Set position to the new position
- SetPosition(a_NewPosition);
- FreezeInternal(a_NewPosition, false);
+ // Set position to the new position
+ SetPosition(a_NewPosition);
+ FreezeInternal(a_NewPosition, false);
- // Stop all mobs from targeting this player
- StopEveryoneFromTargetingMe();
+ // Stop all mobs from targeting this player
+ StopEveryoneFromTargetingMe();
- // Send the respawn packet:
- if (a_ShouldSendRespawn && (m_ClientHandle != nullptr))
- {
- m_ClientHandle->SendRespawn(a_World->GetDimension());
- }
+ cClientHandle * ch = this->GetClientHandle();
+ if (ch != nullptr)
+ {
+ // Send the respawn packet:
+ if (a_ShouldSendRespawn)
+ {
+ m_ClientHandle->SendRespawn(a_World->GetDimension());
+ }
- // Update the view distance.
- m_ClientHandle->SetViewDistance(m_ClientHandle->GetRequestedViewDistance());
- // Send current weather of target world to player
- if (a_World->GetDimension() == dimOverworld)
- {
- m_ClientHandle->SendWeather(a_World->GetWeather());
- }
+ // Update the view distance.
+ ch->SetViewDistance(m_ClientHandle->GetRequestedViewDistance());
- // Broadcast the player into the new world.
- a_World->BroadcastSpawnEntity(*this);
+ // Send current weather of target world to player
+ if (a_World->GetDimension() == dimOverworld)
+ {
+ ch->SendWeather(a_World->GetWeather());
+ }
+ }
+
+ // Broadcast the player into the new world.
+ a_World->BroadcastSpawnEntity(*this);
+
+ // Queue add to new world and removal from the old one
+
+ SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
+ cChunk * ParentChunk = this->GetParentChunk();
- // Queue add to new world and removal from the old one
- cChunk * ParentChunk = GetParentChunk();
- cWorld * OldWorld = GetWorld();
- SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
- OldWorld->QueueTask([this, ParentChunk, a_World](cWorld & a_OldWorld)
- {
LOGD("Warping player \"%s\" from world \"%s\" to \"%s\". Source chunk: (%d, %d) ",
this->GetName().c_str(),
a_OldWorld.GetName().c_str(), a_World->GetName().c_str(),
ParentChunk->GetPosX(), ParentChunk->GetPosZ()
);
ParentChunk->RemoveEntity(this);
- a_World->AddPlayer(this, &a_OldWorld); // New world will appropriate and announce client at his next tick
+ a_World->AddPlayer(this, &a_OldWorld); // New world will take over and announce client at its next tick
});
+
return true;
}
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index f6e9da45e..25796ee50 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -467,6 +467,9 @@ public:
// tolua_end
+ // TODO lua export GetBedPos and GetBedWorld
+ cWorld * GetBedWorld();
+
/** Update movement-related statistics. */
void UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround);
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index c4f705668..2f90a56cb 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -369,6 +369,11 @@ AString cProjectileEntity::GetMCAClassName(void) const
void cProjectileEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
BroadcastMovementUpdate();
}
diff --git a/src/Entities/TNTEntity.cpp b/src/Entities/TNTEntity.cpp
index 4d533ebe4..6784f19f5 100644
--- a/src/Entities/TNTEntity.cpp
+++ b/src/Entities/TNTEntity.cpp
@@ -57,6 +57,11 @@ void cTNTEntity::Explode(void)
void cTNTEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
BroadcastMovementUpdate();
m_FuseTicks -= 1;