diff options
Diffstat (limited to 'src/Entities/Entity.cpp')
-rw-r--r-- | src/Entities/Entity.cpp | 180 |
1 files changed, 179 insertions, 1 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index db0fd0fd6..a7340a29c 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -37,6 +37,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_Gravity(-9.81f) , m_LastPos(a_X, a_Y, a_Z) , m_IsInitialized(false) + , m_WorldTravellingFrom(NULL) , m_EntityType(a_EntityType) , m_World(NULL) , m_IsFireproof(false) @@ -614,6 +615,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) // Handle drowning HandleAir(); } + DetectPortal(); // None of the above functions change position, we remain in the chunk of NextChunk HandlePhysics(a_Dt, *NextChunk); @@ -853,7 +855,7 @@ void cEntity::TickBurning(cChunk & a_Chunk) // Remember the current burning state: bool HasBeenBurning = (m_TicksLeftBurning > 0); - if (m_World->IsWeatherWet()) + if (GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT)) { if (POSY_TOINT > m_World->GetHeight(POSX_TOINT, POSZ_TOINT)) { @@ -1024,6 +1026,182 @@ void cEntity::DetectCacti(void) +void cEntity::DetectPortal() +{ + if (GetWorld()->GetDimension() == dimOverworld) + { + if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) + { + return; + } + } + else if (GetWorld()->GetLinkedOverworldName().empty()) + { + return; + } + + int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; + if ((Y > 0) && (Y < cChunkDef::Height)) + { + switch (GetWorld()->GetBlock(X, Y, Z)) + { + case E_BLOCK_NETHER_PORTAL: + { + if (m_PortalCooldownData.m_ShouldPreventTeleportation) + { + return; + } + + if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80) + { + m_PortalCooldownData.m_TicksDelayed++; + return; + } + m_PortalCooldownData.m_TicksDelayed = 0; + + switch (GetWorld()->GetDimension()) + { + case dimNether: + { + if (GetWorld()->GetLinkedOverworldName().empty()) + { + return; + } + + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + + if (IsPlayer()) + { + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); + } + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + + return; + } + case dimOverworld: + { + if (GetWorld()->GetNetherWorldName().empty()) + { + return; + } + + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + + if (IsPlayer()) + { + ((cPlayer *)this)->AwardAchievement(achEnterPortal); + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); + } + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); + + return; + } + default: return; + } + } + case E_BLOCK_END_PORTAL: + { + if (m_PortalCooldownData.m_ShouldPreventTeleportation) + { + return; + } + + switch (GetWorld()->GetDimension()) + { + case dimEnd: + { + if (GetWorld()->GetLinkedOverworldName().empty()) + { + return; + } + + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + + if (IsPlayer()) + { + cPlayer * Player = (cPlayer *)this; + Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); + Player->GetClientHandle()->SendRespawn(dimOverworld); + } + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + + return; + } + case dimOverworld: + { + if (GetWorld()->GetEndWorldName().empty()) + { + return; + } + + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + + if (IsPlayer()) + { + ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd); + } + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); + + return; + } + default: return; + } + } + default: break; + } + } + + // Allow portals to work again + m_PortalCooldownData.m_ShouldPreventTeleportation = false; + m_PortalCooldownData.m_ShouldPreventTeleportation = 0; +} + + + + + +bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) +{ + UNUSED(a_ShouldSendRespawn); + ASSERT(a_World == NULL); + + if (GetWorld() == a_World) + { + // Don't move to same world + return false; + } + + // Remove all links to the old world + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + GetWorld()->BroadcastDestroyEntity(*this); + + // Queue add to new world + a_World->AddEntity(this); + + return true; +} + + + + + +bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn) +{ + cWorld * World = cRoot::Get()->GetWorld(a_WorldName); + if (World == NULL) + { + LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str()); + return false; + } + + return MoveToWorld(World, a_ShouldSendRespawn); +} + + + + + void cEntity::SetSwimState(cChunk & a_Chunk) { int RelY = (int)floor(GetPosY() + 0.1); |