From 5625598afac8db3b35d790b8d1228997b228f228 Mon Sep 17 00:00:00 2001 From: LogicParrot Date: Sat, 3 Sep 2016 10:39:52 +0300 Subject: Improve cPlayer::DoMoveToWorld (#3113) --- src/ClientHandle.cpp | 1 - src/ClientHandle.h | 3 +- src/Entities/Player.cpp | 79 +++++++++++++++++++++++++++---------------------- 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 6febbfc3a..303583769 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -603,7 +603,6 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunk -// Removes the client from all chunks. Used when switching worlds or destroying the player void cClientHandle::RemoveFromAllChunks() { cWorld * World = m_Player->GetWorld(); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index da59bdea8..7d829653b 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -125,7 +125,8 @@ public: // tolua_export /** Remove all loaded chunks that are no longer in range */ void UnloadOutOfRangeChunks(void); - // Removes the client from all chunks. Used when switching worlds or destroying the player + /** Removes the client from all chunks. Used when destroying the player. + When switching worlds, RemoveFromWorld does this function's job so it isn't called. */ void RemoveFromAllChunks(void); inline bool IsLoggedIn(void) const { return (m_State >= csAuthenticating); } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index f28258969..889aef778 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1780,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; } -- cgit v1.2.3