diff options
Diffstat (limited to '')
-rw-r--r-- | src/Entities/ArrowEntity.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Boat.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Entity.cpp | 47 | ||||
-rw-r--r-- | src/Entities/FireworkEntity.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Minecart.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Pawn.cpp | 6 | ||||
-rw-r--r-- | src/Entities/Pickup.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 88 | ||||
-rw-r--r-- | src/Entities/Player.h | 3 | ||||
-rw-r--r-- | src/Entities/ProjectileEntity.cpp | 5 | ||||
-rw-r--r-- | src/Entities/TNTEntity.cpp | 5 |
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; |