diff options
Diffstat (limited to 'src/Entities/Entity.cpp')
-rw-r--r-- | src/Entities/Entity.cpp | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 4a909a1fd..bb9d3c44b 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -13,6 +13,7 @@ #include "Player.h" #include "Items/ItemHandler.h" #include "../FastRandom.h" +#include "../NetherPortalScanner.h" @@ -42,6 +43,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d m_WorldTravellingFrom(nullptr), m_EntityType(a_EntityType), m_World(nullptr), + m_IsWorldChangeScheduled(false), m_IsFireproof(false), m_TicksSinceLastBurnDamage(0), m_TicksSinceLastLavaDamage(0), @@ -396,7 +398,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) } } - int ThornsLevel = 0; + unsigned int ThornsLevel = 0; const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() }; for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++) { @@ -742,6 +744,13 @@ void cEntity::KilledBy(TakeDamageInfo & a_TDI) return; } + // If the victim is a player the hook is handled by the cPlayer class + if (!IsPlayer()) + { + AString emptystring = AString(""); + cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, emptystring); + } + // Drop loot: cItems Drops; GetDrops(Drops, a_TDI.Attacker); @@ -1260,9 +1269,35 @@ void cEntity::DetectCacti(void) +void cEntity::ScheduleMoveToWorld(cWorld * a_World, Vector3d a_NewPosition, bool a_SetPortalCooldown) +{ + m_NewWorld = a_World; + m_NewWorldPosition = a_NewPosition; + m_IsWorldChangeScheduled = true; + m_WorldChangeSetPortalCooldown = a_SetPortalCooldown; +} + + + bool cEntity::DetectPortal() { + // If somebody scheduled a world change with ScheduleMoveToWorld, change worlds now. + if (m_IsWorldChangeScheduled) + { + m_IsWorldChangeScheduled = false; + + if (m_WorldChangeSetPortalCooldown) + { + // Delay the portal check. + m_PortalCooldownData.m_TicksDelayed = 0; + m_PortalCooldownData.m_ShouldPreventTeleportation = true; + } + + MoveToWorld(m_NewWorld, false, m_NewWorldPosition); + return true; + } + if (GetWorld()->GetDimension() == dimOverworld) { if (GetWorld()->GetLinkedNetherWorldName().empty() && GetWorld()->GetLinkedEndWorldName().empty()) @@ -1312,8 +1347,15 @@ bool cEntity::DetectPortal() // Send a respawn packet before world is loaded / generated so the client isn't left in limbo ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); } - - return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + + Vector3d TargetPos = GetPosition(); + TargetPos.x *= 8.0; + TargetPos.z *= 8.0; + + cWorld * TargetWorld = cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName(), dimNether, GetWorld()->GetName(), false); + LOGD("Jumping nether -> overworld"); + new cNetherPortalScanner(this, TargetWorld, TargetPos, 256); + return true; } else { @@ -1329,8 +1371,15 @@ bool cEntity::DetectPortal() ((cPlayer *)this)->AwardAchievement(achEnterPortal); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); } - - return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedNetherWorldName(), dimNether, GetWorld()->GetName()), false); + + Vector3d TargetPos = GetPosition(); + TargetPos.x /= 8.0; + TargetPos.z /= 8.0; + + cWorld * TargetWorld = cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedNetherWorldName(), dimNether, GetWorld()->GetName(), false); + LOGD("Jumping overworld -> nether"); + new cNetherPortalScanner(this, TargetWorld, TargetPos, 128); + return true; } } case E_BLOCK_END_PORTAL: @@ -1392,7 +1441,7 @@ bool cEntity::DetectPortal() -bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) +bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) { UNUSED(a_ShouldSendRespawn); ASSERT(a_World != nullptr); @@ -1403,14 +1452,27 @@ bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) return false; } + // Ask the plugins if the entity is allowed to changing the world + if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World)) + { + // A Plugin doesn't allow the entity to changing the world + return false; + } + // Remove all links to the old world SetWorldTravellingFrom(GetWorld()); // cChunk::Tick() handles entity removal GetWorld()->BroadcastDestroyEntity(*this); + SetPosition(a_NewPosition); + // Queue add to new world a_World->AddEntity(this); + cWorld * OldWorld = cRoot::Get()->GetWorld(GetWorld()->GetName()); // Required for the hook HOOK_ENTITY_CHANGED_WORLD SetWorld(a_World); + // Entity changed the world, call the hook + cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, *OldWorld); + return true; } @@ -1427,7 +1489,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn) return false; } - return DoMoveToWorld(World, a_ShouldSendRespawn); + return DoMoveToWorld(World, a_ShouldSendRespawn, GetPosition()); } |