diff options
author | Tiger Wang <ziwei.tiger@hotmail.co.uk> | 2016-12-18 19:31:44 +0100 |
---|---|---|
committer | Tiger Wang <ziwei.tiger@hotmail.co.uk> | 2016-12-18 19:31:44 +0100 |
commit | 1f109febbaae43612c8f47058055ce3b101b3b12 (patch) | |
tree | 92ff2e9a36cc0c78bed7f7ec038bfa24fb5df433 /src/Entities/Player.cpp | |
parent | Added cWorld:SetSpawn() API and Lua binding (#3316) (diff) | |
download | cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.tar cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.tar.gz cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.tar.bz2 cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.tar.lz cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.tar.xz cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.tar.zst cuberite-1f109febbaae43612c8f47058055ce3b101b3b12.zip |
Diffstat (limited to '')
-rw-r--r-- | src/Entities/Player.cpp | 544 |
1 files changed, 301 insertions, 243 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index e4c0fdaa5..babe31978 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -36,6 +36,14 @@ // 1000 = once per second #define PLAYER_LIST_TIME_MS std::chrono::milliseconds(1000) +#define DO_WITH_VALID_CLIENTHANDLE(Command) \ + auto ClientHandle = m_ClientHandle.lock(); \ + if (ClientHandle != nullptr) \ + { \ + ClientHandle->Command \ + } + + @@ -50,7 +58,7 @@ const int cPlayer::EATING_TICKS = 30; -cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) : +cPlayer::cPlayer(std::weak_ptr<cClientHandle> a_Client, const AString & a_PlayerName) : super(etPlayer, 0.6, 1.8), m_bVisible(true), m_FoodLevel(MAX_FOOD_LEVEL), @@ -85,8 +93,8 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) : m_FloaterID(cEntity::INVALID_ID), m_Team(nullptr), m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL), - m_bIsTeleporting(false), - m_UUID((a_Client != nullptr) ? a_Client->GetUUID() : ""), + m_IsChangingWorlds(false), + m_UUID(a_Client.lock()->GetUUID()), m_CustomName("") { ASSERT(a_PlayerName.length() <= 16); // Otherwise this player could crash many clients... @@ -148,25 +156,6 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) : -bool cPlayer::Initialize(cWorld & a_World) -{ - UNUSED(a_World); - ASSERT(GetWorld() != nullptr); - ASSERT(GetParentChunk() == nullptr); - GetWorld()->AddPlayer(this); - - cPluginManager::Get()->CallHookSpawnedEntity(*GetWorld(), *this); - - // Spawn the entity on the clients: - GetWorld()->BroadcastSpawnEntity(*this); - - return true; -} - - - - - cPlayer::~cPlayer(void) { if (!cRoot::Get()->GetPluginManager()->CallHookPlayerDestroyed(*this)) @@ -180,10 +169,6 @@ cPlayer::~cPlayer(void) // Notify the server that the player is being destroyed cRoot::Get()->GetServer()->PlayerDestroying(this); - SaveToDisk(); - - m_ClientHandle = nullptr; - delete m_InventoryWindow; m_InventoryWindow = nullptr; @@ -196,6 +181,7 @@ cPlayer::~cPlayer(void) void cPlayer::Destroyed() { + SaveToDisk(); CloseWindow(false); super::Destroyed(); } @@ -206,7 +192,7 @@ void cPlayer::Destroyed() void cPlayer::SpawnOn(cClientHandle & a_Client) { - if (!m_bVisible || (m_ClientHandle.get() == (&a_Client))) + if (!m_bVisible || (m_ClientHandle.lock().get() == &a_Client)) { return; } @@ -225,28 +211,22 @@ void cPlayer::SpawnOn(cClientHandle & a_Client) void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { - if (m_ClientHandle != nullptr) + auto ClientHandle = m_ClientHandle.lock(); + if ((ClientHandle == nullptr) || ClientHandle->IsDestroyed()) { - if (m_ClientHandle->IsDestroyed()) - { - // This should not happen, because destroying a client will remove it from the world, but just in case - ASSERT(!"Player ticked whilst in the process of destruction!"); - m_ClientHandle = nullptr; - return; - } + // If the ClientHandle was deleted or destroyed, the client has disconnected + // In theory, if it was only destroyed, we may continue ticking (just nothing would be sent over the network) + // For performance however, simply bail out - if (!m_ClientHandle->IsPlaying()) - { - // We're not yet in the game, ignore everything - return; - } + return; } - else + + if (!ClientHandle->IsPlaying()) { - ASSERT(!"Player ticked whilst in the process of destruction!"); + // We're not yet in the game, ignore everything + return; } - m_Stats.AddValue(statMinutesPlayed, 1); // Handle a frozen player @@ -255,9 +235,8 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { return; } - ASSERT((GetParentChunk() != nullptr) && (GetParentChunk()->IsValid())); - ASSERT(a_Chunk.IsValid()); + ASSERT(GetParentChunk() != nullptr); super::Tick(a_Dt, a_Chunk); @@ -273,7 +252,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) SendExperience(); } - BroadcastMovementUpdate(m_ClientHandle.get()); + BroadcastMovementUpdate(ClientHandle.get()); if (m_Health > 0) // make sure player is alive { @@ -319,55 +298,16 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cPlayer::TickFreezeCode() { - if (m_IsFrozen) + if (m_IsFrozen && (GetWorld()->GetWorldAge() % 100 == 0)) { - if ((!m_IsManuallyFrozen) && (GetClientHandle()->IsPlayerChunkSent())) - { - // If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded and sent - Unfreeze(); + // Despite the client side freeze, the player may be able to move a little by + // Jumping or canceling flight. Re-freeze every now and then + Freeze(GetPosition()); - // Pull the player out of any solids that might have loaded on them. - PREPARE_REL_AND_CHUNK(GetPosition(), *(GetParentChunk())); - if (RelSuccess) - { - int NewY = Rel.y; - if (NewY < 0) - { - NewY = 0; - } - while (NewY < cChunkDef::Height - 2) - { - // If we find a position with enough space for the player - if ( - (Chunk->GetBlock(Rel.x, NewY, Rel.z) == E_BLOCK_AIR) && - (Chunk->GetBlock(Rel.x, NewY + 1, Rel.z) == E_BLOCK_AIR) - ) - { - // If the found position is not the same as the original - if (NewY != Rel.y) - { - SetPosition(GetPosition().x, NewY, GetPosition().z); - GetClientHandle()->SendPlayerPosition(); - } - break; - } - ++NewY; - } - } - } - else if (GetWorld()->GetWorldAge() % 100 == 0) - { - // Despite the client side freeze, the player may be able to move a little by - // Jumping or canceling flight. Re-freeze every now and then - FreezeInternal(GetPosition(), m_IsManuallyFrozen); - } - } - else - { - if (!GetClientHandle()->IsPlayerChunkSent() || (!GetParentChunk()->IsValid())) - { - FreezeInternal(GetPosition(), false); - } + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerPosition(); + BroadcastMovementUpdate(ClientHandle.get()); + ) } } @@ -499,7 +439,7 @@ void cPlayer::StartChargingBow(void) LOGD("Player \"%s\" started charging their bow", GetName().c_str()); m_IsChargingBow = true; m_BowCharge = 0; - m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); + m_World->BroadcastEntityMetadata(*this, m_ClientHandle.lock().get()); } @@ -512,7 +452,7 @@ int cPlayer::FinishChargingBow(void) int res = m_BowCharge; m_IsChargingBow = false; m_BowCharge = 0; - m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); + m_World->BroadcastEntityMetadata(*this, m_ClientHandle.lock().get()); return res; } @@ -526,7 +466,7 @@ void cPlayer::CancelChargingBow(void) LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", GetName().c_str(), m_BowCharge); m_IsChargingBow = false; m_BowCharge = 0; - m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); + m_World->BroadcastEntityMetadata(*this, m_ClientHandle.lock().get()); } @@ -654,7 +594,11 @@ void cPlayer::FinishEating(void) m_EatingFinishTick = -1; // Send the packets: - m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted); + auto ClientHandle = m_ClientHandle.lock(); + if (ClientHandle == nullptr) + { + ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted); + } m_World->BroadcastEntityMetadata(*this); // consume the item: @@ -684,10 +628,9 @@ void cPlayer::AbortEating(void) void cPlayer::SendHealth(void) { - if (m_ClientHandle != nullptr) - { - m_ClientHandle->SendHealth(); - } + DO_WITH_VALID_CLIENTHANDLE( + SendHealth(); + ) } @@ -696,11 +639,10 @@ void cPlayer::SendHealth(void) void cPlayer::SendExperience(void) { - if (m_ClientHandle != nullptr) - { - m_ClientHandle->SendExperience(); + DO_WITH_VALID_CLIENTHANDLE( + SendExperience(); m_bDirtyExperience = false; - } + ) } @@ -762,8 +704,9 @@ void cPlayer::SetNormalMaxSpeed(double a_Speed) m_NormalMaxSpeed = a_Speed; if (!m_IsSprinting && !m_IsFlying && !m_IsFrozen) { - // If we are frozen, we do not send this yet. We send when unfreeze() is called - m_ClientHandle->SendPlayerMaxSpeed(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerMaxSpeed(); + ) } } @@ -776,8 +719,9 @@ void cPlayer::SetSprintingMaxSpeed(double a_Speed) m_SprintingMaxSpeed = a_Speed; if (m_IsSprinting && !m_IsFlying && !m_IsFrozen) { - // If we are frozen, we do not send this yet. We send when unfreeze() is called - m_ClientHandle->SendPlayerMaxSpeed(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerMaxSpeed(); + ) } } @@ -789,11 +733,13 @@ void cPlayer::SetFlyingMaxSpeed(double a_Speed) { m_FlyingMaxSpeed = a_Speed; - // Update the flying speed, always: + // Update the flying speed: if (!m_IsFrozen) { // If we are frozen, we do not send this yet. We send when unfreeze() is called - m_ClientHandle->SendPlayerAbilities(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerAbilities(); + ) } } @@ -827,7 +773,9 @@ void cPlayer::SetSprint(bool a_IsSprinting) } m_IsSprinting = a_IsSprinting; - m_ClientHandle->SendPlayerMaxSpeed(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerMaxSpeed(); + ) } @@ -842,7 +790,9 @@ void cPlayer::SetCanFly(bool a_CanFly) } m_CanFly = a_CanFly; - m_ClientHandle->SendPlayerAbilities(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerAbilities(); + ) } @@ -904,7 +854,9 @@ void cPlayer::SetFlying(bool a_IsFlying) if (!m_IsFrozen) { // If we are frozen, we do not send this yet. We send when unfreeze() is called - m_ClientHandle->SendPlayerAbilities(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerAbilities(); + ) } } @@ -1147,18 +1099,20 @@ void cPlayer::Respawn(void) m_LifetimeTotalXp = 0; // ToDo: send score to client? How? - m_ClientHandle->SendRespawn(m_SpawnWorld->GetDimension(), true); + DO_WITH_VALID_CLIENTHANDLE( + SendRespawn(m_SpawnWorld->GetDimension(), true); + ) // Extinguish the fire: StopBurning(); if (GetWorld() != m_SpawnWorld) { - MoveToWorld(m_SpawnWorld, false, GetLastBedPos()); + MoveToWorld(*m_SpawnWorld, GetLastBedPos()); } else { - TeleportToCoords(GetLastBedPos().x, GetLastBedPos().y, GetLastBedPos().z); + TeleportToCoords(GetLastBedPos()); } SetVisible(true); @@ -1335,7 +1289,9 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) } m_GameMode = a_GameMode; - m_ClientHandle->SendGameMode(a_GameMode); + DO_WITH_VALID_CLIENTHANDLE( + SendGameMode(a_GameMode); + ) SetCapabilities(); @@ -1422,7 +1378,9 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach) StatValue New = m_Stats.AddValue(a_Ach); // Achievement Get! - m_ClientHandle->SendStatistics(m_Stats); + DO_WITH_VALID_CLIENTHANDLE( + SendStatistics(m_Stats); + ) return static_cast<unsigned int>(New); } @@ -1432,18 +1390,18 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach) -void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) +void cPlayer::TeleportToCoords(const Vector3d & a_Position) { - // ask plugins to allow teleport to the new position. - if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ))) + // Ask plugins to allow teleport to the new position. + if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, a_Position)) { - SetPosition(a_PosX, a_PosY, a_PosZ); - FreezeInternal(GetPosition(), false); - m_LastGroundHeight = a_PosY; - m_bIsTeleporting = true; + SetPosition(a_Position); + m_LastGroundHeight = a_Position.y; m_World->BroadcastTeleportEntity(*this, GetClientHandle()); - m_ClientHandle->SendPlayerMoveLook(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerMoveLook(); + ) } } @@ -1453,7 +1411,32 @@ void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) void cPlayer::Freeze(const Vector3d & a_Location) { - FreezeInternal(a_Location, true); + SetSpeed(0, 0, 0); + SetPosition(a_Location); + m_IsFrozen = true; + + double NormalMaxSpeed = GetNormalMaxSpeed(); + double SprintMaxSpeed = GetSprintingMaxSpeed(); + double FlyingMaxpeed = GetFlyingMaxSpeed(); + bool IsFlying = m_IsFlying; + + // Set the client-side speed to 0 + m_NormalMaxSpeed = 0; + m_SprintingMaxSpeed = 0; + m_FlyingMaxSpeed = 0; + m_IsFlying = true; + + // Send the client its fake speed and max speed of 0 + GetClientHandle()->SendPlayerMoveLook(); + GetClientHandle()->SendPlayerAbilities(); + GetClientHandle()->SendPlayerMaxSpeed(); + GetClientHandle()->SendEntityVelocity(*this); + + // Keep the server side speed variables as they were in the first place + m_NormalMaxSpeed = NormalMaxSpeed; + m_SprintingMaxSpeed = SprintMaxSpeed; + m_FlyingMaxSpeed = FlyingMaxpeed; + m_IsFlying = IsFlying; } @@ -1475,8 +1458,10 @@ void cPlayer::Unfreeze() GetClientHandle()->SendPlayerMaxSpeed(); m_IsFrozen = false; - BroadcastMovementUpdate(GetClientHandle()); - GetClientHandle()->SendPlayerPosition(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerPosition(); + BroadcastMovementUpdate(ClientHandle.get()); + ) } @@ -1487,7 +1472,9 @@ void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees) { SetYaw(a_YawDegrees); SetPitch(a_PitchDegrees); - m_ClientHandle->SendPlayerMoveLook(); + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerMoveLook(); + ) } @@ -1524,15 +1511,6 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const -void cPlayer::ForceSetSpeed(const Vector3d & a_Speed) -{ - SetSpeed(a_Speed); -} - - - - - void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) { if (m_IsFrozen) @@ -1542,7 +1520,9 @@ void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) } super::DoSetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ); // Send the speed to the client so he actualy moves - m_ClientHandle->SendEntityVelocity(*this); + DO_WITH_VALID_CLIENTHANDLE( + SendEntityVelocity(*this); + ) } @@ -1560,10 +1540,120 @@ void cPlayer::SetVisible(bool a_bVisible) if (!a_bVisible && m_bVisible) { m_bVisible = false; - m_World->BroadcastDestroyEntity(*this, m_ClientHandle.get()); // Destroy on all clients + m_World->BroadcastDestroyEntity(*this, m_ClientHandle.lock().get()); // Destroy on all clients } } +void cPlayer::SendMessage(const AString & a_Message) +{ + SendMessage(cCompositeChat(a_Message, mtCustom)); +} + + + + + +void cPlayer::SendMessageInfo(const AString & a_Message) +{ + SendMessage(cCompositeChat(a_Message, mtInformation)); +} + + + + + +void cPlayer::SendMessageFailure(const AString & a_Message) +{ + SendMessage(cCompositeChat(a_Message, mtFailure)); +} + + + + + +void cPlayer::SendMessageSuccess(const AString & a_Message) +{ + SendMessage(cCompositeChat(a_Message, mtSuccess)); +} + + + + + +void cPlayer::SendMessageWarning(const AString & a_Message) +{ + SendMessage(cCompositeChat(a_Message, mtWarning)); +} + + + + + +void cPlayer::SendMessageFatal(const AString & a_Message) +{ + SendMessage(cCompositeChat(a_Message, mtFailure)); +} + + + + + +void cPlayer::SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) +{ + SendMessage(cCompositeChat(a_Message, mtPrivateMessage, a_Sender)); +} + + + + + +void cPlayer::SendMessage(const cCompositeChat & a_Message) +{ + DO_WITH_VALID_CLIENTHANDLE( + SendChat(a_Message); + ) +} + + + + + +void cPlayer::SendSystemMessage(const AString & a_Message) +{ + SendSystemMessage(cCompositeChat(a_Message)); +} + + + + + +void cPlayer::SendAboveActionBarMessage(const AString & a_Message) +{ + SendAboveActionBarMessage(cCompositeChat(a_Message)); +} + + + + + +void cPlayer::SendSystemMessage(const cCompositeChat & a_Message) +{ + DO_WITH_VALID_CLIENTHANDLE( + SendChatSystem(a_Message); + ) +} + + + + + +void cPlayer::SendAboveActionBarMessage(const cCompositeChat & a_Message) +{ + DO_WITH_VALID_CLIENTHANDLE( + SendChatAboveActionBar(a_Message); + ) +} + @@ -1760,77 +1850,94 @@ void cPlayer::TossItems(const cItems & a_Items) -bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) +bool cPlayer::OnPreWorldTravel(cWorld & a_NewWorld) { - ASSERT(a_World != nullptr); - ASSERT(IsTicking()); - - if (GetWorld() == a_World) + if ((GetWorld() == &a_NewWorld) || IsChangingWorlds()) { - // Don't move to same world + // Don't move a) to same world or b) when already moving worlds return false; } + ASSERT(IsTicking()); // Ask the plugins if the player is allowed to changing the world - if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World)) + if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, a_NewWorld)) { // A Plugin doesn't allow the player to changing the world return false; } - // The clienthandle caches the coords of the chunk we're standing at. Invalidate this. - GetClientHandle()->InvalidateCachedSentChunk(); - // Prevent further ticking in this world SetIsTicking(false); - // Tell others we are gone + // Stop sending chunks + SetIsChangingWorlds(true); + + auto ClientHandle = GetClientHandlePtr().lock(); + if (ClientHandle != nullptr) + { + cRoot::Get()->GetServer()->QueueTask( + [ClientHandle] + { + ClientHandle->RemoveFromWorld(); + } + ); + + GetWorld()->RemovePlayer(this); + ClientHandle->SendRespawn(a_NewWorld.GetDimension()); + + switch (a_NewWorld.GetDimension()) + { + case eDimension::dimOverworld: break; + case eDimension::dimNether: AwardAchievement(achEnterPortal); break; + case eDimension::dimEnd: AwardAchievement(achEnterTheEnd); break; + default: ASSERT(!"Unexpected dimension during world travel."); + } + } + // If std::weak_ptr<>::lock returned nullptr, the destructor of cClientHandle would have handled player removal. + + auto Entity = GetParentChunk()->AcquireAssociatedEntityPtr(*this); + + // Broadcast for other people that the player is gone. GetWorld()->BroadcastDestroyEntity(*this); - // Remove player from world - GetWorld()->RemovePlayer(this, false); + cpp14::move_on_copy_wrapper<decltype(Entity)> EntityPtr(std::move(Entity)); + a_NewWorld.QueueTask( + [EntityPtr](cWorld & a_DestinationWorld) mutable + { + ASSERT(EntityPtr.value->IsPlayer()); + auto Player = static_cast<cPlayer *>(EntityPtr.value.get()); - // Set position to the new position - SetPosition(a_NewPosition); - FreezeInternal(a_NewPosition, false); + // Player changed world, call the hook + cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*EntityPtr.value, *EntityPtr.value->GetWorld()); - // Stop all mobs from targeting this player - StopEveryoneFromTargetingMe(); + EntityPtr.value->Initialize(std::move(EntityPtr.value), a_DestinationWorld); + a_DestinationWorld.AddPlayer(Player); - // Send the respawn packet: - if (a_ShouldSendRespawn && (m_ClientHandle != nullptr)) - { - m_ClientHandle->SendRespawn(a_World->GetDimension()); - } + Player->SetIsChangingWorlds(false); + } + ); + + return true; +} - // 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()); - } - // Broadcast the player into the new world. - a_World->BroadcastSpawnEntity(*this); - // 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) + +void cPlayer::OnPostWorldTravel(eDimension a_PreviousDimension, const Vector3d & a_RecommendedPosition) +{ + if ((a_PreviousDimension == eDimension::dimEnd) && (GetWorld()->GetDimension() == eDimension::dimOverworld)) { - 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); - cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, a_OldWorld); - }); - return true; + super::OnPostWorldTravel(a_PreviousDimension, GetLastBedPos()); + } + else + { + super::OnPostWorldTravel(a_PreviousDimension, a_RecommendedPosition); + } + + DO_WITH_VALID_CLIENTHANDLE( + SendPlayerMoveLook(); + ) } @@ -2251,12 +2358,6 @@ bool cPlayer::IsClimbing(void) const void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround) { - if (m_bIsTeleporting) - { - m_bIsTeleporting = false; - return; - } - StatValue Value = FloorC<StatValue>(a_DeltaPos.Length() * 100 + 0.5); if (m_AttachedTo == nullptr) { @@ -2412,7 +2513,9 @@ void cPlayer::SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_R // Send the blocks for each affected chunk: for (auto itr = Changes.cbegin(), end = Changes.cend(); itr != end; ++itr) { - m_ClientHandle->SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second); + DO_WITH_VALID_CLIENTHANDLE( + SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second); + ) } } @@ -2449,7 +2552,7 @@ bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks) } // Call the "placed" hooks: - for (auto blk: a_Blocks) + for (const auto & blk: a_Blocks) { pm->CallHookPlayerPlacedBlock(*this, blk); } @@ -2482,7 +2585,7 @@ void cPlayer::Detach() cBlockInfo::IsSolid(m_World->GetBlock(x, y - 1, z)) ) { - TeleportToCoords(x + 0.5, y, z + 0.5); + TeleportToCoords(Vector3d(x + 0.5, y, z + 0.5)); return; } } @@ -2494,16 +2597,6 @@ void cPlayer::Detach() -void cPlayer::RemoveClientHandle(void) -{ - ASSERT(m_ClientHandle != nullptr); - m_ClientHandle.reset(); -} - - - - - AString cPlayer::GetUUIDFileName(const AString & a_UUID) { AString UUID = cMojangAPI::MakeUUIDDashed(a_UUID); @@ -2516,38 +2609,3 @@ AString cPlayer::GetUUIDFileName(const AString & a_UUID) res.append(".json"); return res; } - - - - - -void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen) -{ - SetSpeed(0, 0, 0); - SetPosition(a_Location); - m_IsFrozen = true; - m_IsManuallyFrozen = a_ManuallyFrozen; - - double NormalMaxSpeed = GetNormalMaxSpeed(); - double SprintMaxSpeed = GetSprintingMaxSpeed(); - double FlyingMaxpeed = GetFlyingMaxSpeed(); - bool IsFlying = m_IsFlying; - - // Set the client-side speed to 0 - m_NormalMaxSpeed = 0; - m_SprintingMaxSpeed = 0; - m_FlyingMaxSpeed = 0; - m_IsFlying = true; - - // Send the client its fake speed and max speed of 0 - GetClientHandle()->SendPlayerMoveLook(); - GetClientHandle()->SendPlayerAbilities(); - GetClientHandle()->SendPlayerMaxSpeed(); - GetClientHandle()->SendEntityVelocity(*this); - - // Keep the server side speed variables as they were in the first place - m_NormalMaxSpeed = NormalMaxSpeed; - m_SprintingMaxSpeed = SprintMaxSpeed; - m_FlyingMaxSpeed = FlyingMaxpeed; - m_IsFlying = IsFlying; -} |