summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Entities/ArrowEntity.cpp6
-rw-r--r--src/Entities/Entity.cpp149
-rw-r--r--src/Entities/Entity.h34
-rw-r--r--src/Entities/Pawn.cpp5
-rw-r--r--src/Entities/Pickup.cpp17
-rw-r--r--src/Entities/Player.cpp10
6 files changed, 99 insertions, 122 deletions
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index 4d104bd26..2dc329f30 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -123,7 +123,7 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos)
double KnockbackAmount = 11 + 10 * PunchLevel;
a_EntityHit.TakeDamage(dtRangedAttack, GetCreatorUniqueID(), Damage, KnockbackAmount);
- if (IsOnFire() && !a_EntityHit.IsSubmerged() && !a_EntityHit.IsSwimming())
+ if (IsOnFire() && !a_EntityHit.IsInWater())
{
a_EntityHit.StartBurning(100);
}
@@ -218,7 +218,3 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
}
}
}
-
-
-
-
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 646566ae6..ea20fc8da 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -54,8 +54,10 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
m_TicksSinceLastFireDamage(0),
m_TicksLeftBurning(0),
m_TicksSinceLastVoidDamage(0),
- m_IsSwimming(false),
- m_IsSubmerged(false),
+ m_IsInFire(false),
+ m_IsInLava(false),
+ m_IsInWater(false),
+ m_IsHeadInWater(false),
m_AirLevel(MAX_AIR_LEVEL),
m_AirTickTimer(DROWNING_TICKS),
m_TicksAlive(0),
@@ -477,11 +479,11 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
{
BurnTicks += 4 * (FireAspectLevel - 1);
}
- if (!IsMob() && !IsSubmerged() && !IsSwimming())
+ if (!IsMob() && !IsInWater())
{
StartBurning(BurnTicks * 20);
}
- else if (IsMob() && !IsSubmerged() && !IsSwimming())
+ else if (IsMob() && !IsInWater())
{
cMonster * Monster = reinterpret_cast<cMonster *>(this);
switch (Monster->GetMobType())
@@ -831,6 +833,7 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_InvulnerableTicks--;
}
+ // Non-players are destroyed as soon as they fall out of the world:
if ((GetPosY() < 0) && (!IsPlayer()))
{
Destroy();
@@ -848,11 +851,16 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
return;
}
- // Position changed -> super::Tick() called
+ // Position changed -> super::Tick() called:
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, POSX_TOINT, POSZ_TOINT)
+ // Set swim states (water, lava, and fire):
+ SetSwimState(*NextChunk);
+
+ // Handle catching on fire and burning:
TickBurning(*NextChunk);
+ // Damage players if they are in the void
if (GetPosY() < VOID_BOUNDARY)
{
TickInVoid(*NextChunk);
@@ -862,6 +870,7 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_TicksSinceLastVoidDamage = 0;
}
+ // Handle cactus damage or destruction:
if (
IsMob() || IsPickup() || IsExpOrb() ||
(IsPlayer() && !((reinterpret_cast<cPlayer *>(this))->IsGameModeCreative() || (reinterpret_cast<cPlayer *>(this))->IsGameModeSpectator()))
@@ -869,12 +878,10 @@ void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
DetectCacti();
}
+
+ // Handle drowning:
if (IsMob() || IsPlayer())
{
- // Set swimming state
- SetSwimState(*NextChunk);
-
- // Handle drowning
HandleAir();
}
@@ -1192,60 +1199,13 @@ void cEntity::TickBurning(cChunk & a_Chunk)
m_TicksLeftBurning--;
}
- // Update the burning times, based on surroundings:
- int MinRelX = FloorC(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
- int MaxRelX = FloorC(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
- int MinRelZ = FloorC(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
- int MaxRelZ = FloorC(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
- int MinY = Clamp(POSY_TOINT, 0, cChunkDef::Height - 1);
- int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1);
- bool HasWater = false;
- bool HasLava = false;
- bool HasFire = false;
-
- for (int x = MinRelX; x <= MaxRelX; x++)
- {
- for (int z = MinRelZ; z <= MaxRelZ; z++)
- {
- int RelX = x;
- int RelZ = z;
-
- for (int y = MinY; y <= MaxY; y++)
- {
- BLOCKTYPE Block;
- a_Chunk.UnboundedRelGetBlockType(RelX, y, RelZ, Block);
-
- switch (Block)
- {
- case E_BLOCK_FIRE:
- {
- HasFire = true;
- break;
- }
- case E_BLOCK_LAVA:
- case E_BLOCK_STATIONARY_LAVA:
- {
- HasLava = true;
- break;
- }
- case E_BLOCK_STATIONARY_WATER:
- case E_BLOCK_WATER:
- {
- HasWater = true;
- break;
- }
- } // switch (BlockType)
- } // for y
- } // for z
- } // for x
-
- if (HasWater)
+ if (IsInWater())
{
// Extinguish the fire
m_TicksLeftBurning = 0;
}
- if (HasLava)
+ if (IsInLava())
{
// Burn:
m_TicksLeftBurning = BURN_TICKS;
@@ -1266,7 +1226,7 @@ void cEntity::TickBurning(cChunk & a_Chunk)
m_TicksSinceLastLavaDamage = 0;
}
- if (HasFire)
+ if (IsInFire())
{
// Burn:
m_TicksLeftBurning = BURN_TICKS;
@@ -1275,7 +1235,7 @@ void cEntity::TickBurning(cChunk & a_Chunk)
m_TicksSinceLastFireDamage++;
if (m_TicksSinceLastFireDamage >= FIRE_TICKS_PER_DAMAGE)
{
- if (!IsFireproof() && !HasLava)
+ if (!IsFireproof() && !IsInLava())
{
TakeDamage(dtFireContact, nullptr, FIRE_DAMAGE, 0);
}
@@ -1644,37 +1604,70 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn)
void cEntity::SetSwimState(cChunk & a_Chunk)
{
+ m_IsInFire = false;
+ m_IsInLava = false;
+ m_IsInWater = false;
+ m_IsHeadInWater = false;
+
int RelY = FloorC(GetPosY() + 0.1);
int HeadRelY = CeilC(GetPosY() + GetHeight()) - 1;
ASSERT(RelY <= HeadRelY);
if ((RelY < 0) || (HeadRelY >= cChunkDef::Height))
{
- m_IsSwimming = false;
- m_IsSubmerged = false;
return;
}
- BLOCKTYPE BlockIn;
+ int MinRelX = FloorC(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
+ int MaxRelX = FloorC(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
+ int MinRelZ = FloorC(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
+ int MaxRelZ = FloorC(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
+ int MinY = Clamp(POSY_TOINT, 0, cChunkDef::Height - 1);
+ int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1);
+
+ for (int x = MinRelX; x <= MaxRelX; x++)
+ {
+ for (int z = MinRelZ; z <= MaxRelZ; z++)
+ {
+ for (int y = MinY; y <= MaxY; y++)
+ {
+ BLOCKTYPE Block;
+ if (!a_Chunk.UnboundedRelGetBlockType(x, y, z, Block))
+ {
+ LOGD("SetSwimState failure: RelX = %d, RelY = %d, RelZ = %d, Pos = %.02f, %.02f}",
+ x, y, z, GetPosX(), GetPosZ()
+ );
+ continue;
+ }
+
+ if (Block == E_BLOCK_FIRE)
+ {
+ m_IsInFire = true;
+ }
+ else if (IsBlockLava(Block))
+ {
+ m_IsInLava = true;
+ }
+ else if (IsBlockWater(Block))
+ {
+ m_IsInWater = true;
+ }
+ } // for y
+ } // for z
+ } // for x
+
+ // Check if the entity's head is in water.
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
-
- // Check if the player is swimming:
- if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
+ int HeadHeight = CeilC(GetPosY() + GetHeight()) - 1;
+ BLOCKTYPE BlockIn;
+ if (!a_Chunk.UnboundedRelGetBlockType(RelX, HeadHeight, RelZ, BlockIn))
{
- // This sometimes happens on Linux machines
- // Ref.: https://forum.cuberite.org/thread-1244.html
- LOGD("SetSwimState failure: RelX = %d, RelZ = %d, Pos = %.02f, %.02f}",
- RelX, RelY, GetPosX(), GetPosZ()
+ LOGD("SetSwimState failure: RelX = %d, RelY = %d, RelZ = %d, Pos = %.02f, %.02f}",
+ RelX, HeadHeight, RelZ, GetPosX(), GetPosZ()
);
- m_IsSwimming = false;
- m_IsSubmerged = false;
return;
}
- m_IsSwimming = IsBlockWater(BlockIn);
-
- // Check if the player is submerged:
- VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, HeadRelY, RelZ, BlockIn));
- m_IsSubmerged = IsBlockWater(BlockIn);
+ m_IsHeadInWater = IsBlockWater(BlockIn);
}
@@ -1710,7 +1703,7 @@ void cEntity::HandleAir(void)
int RespirationLevel = static_cast<int>(GetEquippedHelmet().m_Enchantments.GetLevel(cEnchantments::enchRespiration));
- if (IsSubmerged())
+ if (IsHeadInWater())
{
if (!IsPlayer()) // Players control themselves
{
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index fae296ab4..5b993ac96 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -481,11 +481,17 @@ public:
virtual bool IsRclking (void) const {return false; }
virtual bool IsInvisible(void) const { return false; }
- /** Returns whether the player is swimming or not */
- virtual bool IsSwimming(void) const{ return m_IsSwimming; }
+ /** Returns true if any part of the entity is in a fire block */
+ virtual bool IsInFire(void) const { return m_IsInFire; }
- /** Return whether the player is under water or not */
- virtual bool IsSubmerged(void) const{ return m_IsSubmerged; }
+ /** Returns true if any part of the entity is in a lava block */
+ virtual bool IsInLava(void) const { return m_IsInLava; }
+
+ /** Returns true if any part of the entity is in a water block */
+ virtual bool IsInWater(void) const { return m_IsInWater; }
+
+ /** Returns true if any part of the entity is in a water block */
+ virtual bool IsHeadInWater(void) const { return m_IsHeadInWater; }
/** Gets remaining air of a monster */
int GetAirLevel(void) const { return m_AirLevel; }
@@ -619,8 +625,17 @@ protected:
/** Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. */
int m_TicksSinceLastVoidDamage;
- /** If an entity is currently swimming in or submerged under water */
- bool m_IsSwimming, m_IsSubmerged;
+ /** If any part of the entity is in a fire block */
+ bool m_IsInFire;
+
+ /** If any part of the entity is in a lava block */
+ bool m_IsInLava;
+
+ /** If any part of the entity is in a water block */
+ bool m_IsInWater;
+
+ /** If the entity's head is in a water block */
+ bool m_IsHeadInWater;
/** Air level of a mobile */
int m_AirLevel;
@@ -647,7 +662,8 @@ protected:
/** Called in each tick to handle air-related processing i.e. drowning */
virtual void HandleAir(void);
- /** Called once per tick to set IsSwimming and IsSubmerged */
+ /** Called once per tick to set m_IsInFire, m_IsInLava, m_IsInWater and
+ m_IsHeadInWater */
virtual void SetSwimState(cChunk & a_Chunk);
private:
@@ -693,7 +709,3 @@ private:
cMonsterList m_LeashedMobs;
} ; // tolua_export
-
-
-
-
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index b5769f430..27c04d4b8 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -156,7 +156,7 @@ bool cPawn::IsInvisible() const
void cPawn::HandleAir(void)
{
- if (IsSubmerged() && HasEntityEffect(cEntityEffect::effWaterBreathing))
+ if (IsHeadInWater() && HasEntityEffect(cEntityEffect::effWaterBreathing))
{
// Prevent the oxygen from decreasing
return;
@@ -486,6 +486,3 @@ cEntityEffect * cPawn::GetEntityEffect(cEntityEffect::eType a_EffectType)
auto itr = m_EntityEffects.find(a_EffectType);
return (itr != m_EntityEffects.end()) ? itr->second.get() : nullptr;
}
-
-
-
diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp
index 26fe58252..be6f3ebe3 100644
--- a/src/Entities/Pickup.cpp
+++ b/src/Entities/Pickup.cpp
@@ -147,17 +147,8 @@ void cPickup::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
// Position might have changed due to physics. So we have to make sure we have the correct chunk.
GET_AND_VERIFY_CURRENT_CHUNK(CurrentChunk, BlockX, BlockZ)
- int RelBlockX = BlockX - (CurrentChunk->GetPosX() * cChunkDef::Width);
- int RelBlockZ = BlockZ - (CurrentChunk->GetPosZ() * cChunkDef::Width);
-
- // If the pickup is on the bottommost block position, make it think the void is made of air: (#131)
- BLOCKTYPE BlockBelow = (BlockY > 0) ? CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
- BLOCKTYPE BlockIn = CurrentChunk->GetBlock(RelBlockX, BlockY, RelBlockZ);
-
- if (
- IsBlockLava(BlockBelow) || (BlockBelow == E_BLOCK_FIRE) ||
- IsBlockLava(BlockIn) || (BlockIn == E_BLOCK_FIRE)
- )
+ // Destroy the pickup if it is on fire:
+ if (IsOnFire())
{
m_bCollected = true;
m_Timer = std::chrono::milliseconds(0); // We have to reset the timer.
@@ -261,7 +252,3 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
// LOG("Pickup %d cannot be collected by \"%s\", because there's no space in the inventory.", a_Dest->GetName().c_str(), m_UniqueID);
return false;
}
-
-
-
-
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 073d00909..7b6719f55 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -92,9 +92,6 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
{
ASSERT(a_PlayerName.length() <= 16); // Otherwise this player could crash many clients...
- m_IsSwimming = false;
- m_IsSubmerged = false;
-
m_InventoryWindow = new cInventoryWindow(*this);
m_CurrentWindow = m_InventoryWindow;
m_InventoryWindow->OpenedByPlayer(*this);
@@ -2503,12 +2500,7 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
m_Stats.AddValue(statDistClimbed, FloorC<StatValue>(a_DeltaPos.y * 100 + 0.5));
}
}
- else if (IsSubmerged())
- {
- m_Stats.AddValue(statDistDove, Value);
- AddFoodExhaustion(0.00015 * static_cast<double>(Value));
- }
- else if (IsSwimming())
+ else if (IsInWater())
{
m_Stats.AddValue(statDistSwum, Value);
AddFoodExhaustion(0.00015 * static_cast<double>(Value));