summaryrefslogtreecommitdiffstats
path: root/src/Entities/Entity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities/Entity.cpp')
-rw-r--r--src/Entities/Entity.cpp380
1 files changed, 192 insertions, 188 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 96e8c15a5..3eac0e2e8 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -521,27 +521,35 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
if (a_Chunk.IsValid())
{
- HandlePhysics(a_Dt, a_Chunk);
- }
- }
- if (a_Chunk.IsValid())
- {
- TickBurning(a_Chunk);
- }
- if ((a_Chunk.IsValid()) && (GetPosY() < -46))
- {
- TickInVoid(a_Chunk);
- }
- else
- m_TicksSinceLastVoidDamage = 0;
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(POSX_TOINT, POSZ_TOINT);
- if (IsMob() || IsPlayer())
- {
- // Set swimming state
- SetSwimState(a_Chunk);
+ if ((NextChunk == NULL) || !NextChunk->IsValid())
+ {
+ return;
+ }
+
+ TickBurning(*NextChunk);
- // Handle drowning
- HandleAir();
+ if (GetPosY() < VOID_BOUNDARY)
+ {
+ TickInVoid(*NextChunk);
+ }
+ else
+ {
+ m_TicksSinceLastVoidDamage = 0;
+ }
+
+ if (IsMob() || IsPlayer())
+ {
+ // Set swimming state
+ SetSwimState(*NextChunk);
+
+ // Handle drowning
+ HandleAir();
+ }
+
+ HandlePhysics(a_Dt, *NextChunk);
+ }
}
}
@@ -562,7 +570,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{
// Outside of the world
-
+
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
// See if we can commit our changes. If not, we will discard them.
if (NextChunk != NULL)
@@ -571,210 +579,208 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
NextPos += (NextSpeed * a_Dt);
SetPosition(NextPos);
}
+
return;
}
- // Make sure we got the correct chunk and a valid one. No one ever knows...
- cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
- if (NextChunk != NULL)
+ int RelBlockX = BlockX - (a_Chunk.GetPosX() * cChunkDef::Width);
+ int RelBlockZ = BlockZ - (a_Chunk.GetPosZ() * cChunkDef::Width);
+ BLOCKTYPE BlockIn = a_Chunk.GetBlock( RelBlockX, BlockY, RelBlockZ );
+ BLOCKTYPE BlockBelow = (BlockY > 0) ? a_Chunk.GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
+ if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
{
- int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
- int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
- BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
- BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
- if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
+ if (m_bOnGround) // check if it's still on the ground
{
- if (m_bOnGround) // check if it's still on the ground
+ if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
{
- if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
- {
- m_bOnGround = false;
- }
+ m_bOnGround = false;
}
}
- else
- {
- // Push out entity.
- BLOCKTYPE GotBlock;
+ }
+ else
+ {
+ // Push out entity.
+ BLOCKTYPE GotBlock;
- static const struct
- {
- int x, y, z;
- } gCrossCoords[] =
- {
- { 1, 0, 0},
- {-1, 0, 0},
- { 0, 0, 1},
- { 0, 0, -1},
- } ;
-
- bool IsNoAirSurrounding = true;
- for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
+ static const struct
+ {
+ int x, y, z;
+ } gCrossCoords[] =
+ {
+ { 1, 0, 0},
+ {-1, 0, 0},
+ { 0, 0, 1},
+ { 0, 0, -1},
+ } ;
+
+ bool IsNoAirSurrounding = true;
+ for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
+ {
+ if (!a_Chunk.UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
{
- if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
- {
- // The pickup is too close to an unloaded chunk, bail out of any physics handling
- return;
- }
- if (!cBlockInfo::IsSolid(GotBlock))
- {
- NextPos.x += gCrossCoords[i].x;
- NextPos.z += gCrossCoords[i].z;
- IsNoAirSurrounding = false;
- break;
- }
- } // for i - gCrossCoords[]
-
- if (IsNoAirSurrounding)
+ // The pickup is too close to an unloaded chunk, bail out of any physics handling
+ return;
+ }
+ if (!cBlockInfo::IsSolid(GotBlock))
{
- NextPos.y += 0.5;
+ NextPos.x += gCrossCoords[i].x;
+ NextPos.z += gCrossCoords[i].z;
+ IsNoAirSurrounding = false;
+ break;
}
+ } // for i - gCrossCoords[]
+
+ if (IsNoAirSurrounding)
+ {
+ NextPos.y += 0.5;
+ }
- m_bOnGround = true;
+ m_bOnGround = true;
- /*
- // DEBUG:
- LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
- m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
- );
- */
- }
+ /*
+ // DEBUG:
+ LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
+ m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
+ );
+ */
+ }
- if (!m_bOnGround)
+ if (!m_bOnGround)
+ {
+ float fallspeed;
+ if (IsBlockWater(BlockIn))
{
- float fallspeed;
- if (IsBlockWater(BlockIn))
- {
- fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
- }
- else if (BlockIn == E_BLOCK_COBWEB)
- {
- NextSpeed.y *= 0.05; // Reduce overall falling speed
- fallspeed = 0; // No falling.
- }
- else
- {
- // Normal gravity
- fallspeed = m_Gravity * a_Dt;
- }
- NextSpeed.y += fallspeed;
+ fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
+ }
+ else if (BlockIn == E_BLOCK_COBWEB)
+ {
+ NextSpeed.y *= 0.05; // Reduce overall falling speed
+ fallspeed = 0; // No falling.
}
else
{
- // Friction
- if (NextSpeed.SqrLength() > 0.0004f)
+ // Normal gravity
+ fallspeed = m_Gravity * a_Dt;
+ }
+ NextSpeed.y += fallspeed;
+ }
+ else
+ {
+ // Friction
+ if (NextSpeed.SqrLength() > 0.0004f)
+ {
+ NextSpeed.x *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.x) < 0.05)
{
- NextSpeed.x *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.x) < 0.05)
- {
- NextSpeed.x = 0;
- }
- NextSpeed.z *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.z) < 0.05)
- {
- NextSpeed.z = 0;
- }
+ NextSpeed.x = 0;
+ }
+ NextSpeed.z *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.z) < 0.05)
+ {
+ NextSpeed.z = 0;
}
}
+ }
- // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
- // might have different speed modifiers according to terrain.
- if (BlockIn == E_BLOCK_COBWEB)
- {
- NextSpeed.x *= 0.25;
- NextSpeed.z *= 0.25;
- }
+ // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
+ // might have different speed modifiers according to terrain.
+ if (BlockIn == E_BLOCK_COBWEB)
+ {
+ NextSpeed.x *= 0.25;
+ NextSpeed.z *= 0.25;
+ }
- //Get water direction
- Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
+ //Get water direction
+ Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
- m_WaterSpeed *= 0.9f; //Reduce speed each tick
+ m_WaterSpeed *= 0.9f; //Reduce speed each tick
- switch(WaterDir)
- {
- case X_PLUS:
- m_WaterSpeed.x = 0.2f;
- m_bOnGround = false;
- break;
- case X_MINUS:
- m_WaterSpeed.x = -0.2f;
- m_bOnGround = false;
- break;
- case Z_PLUS:
- m_WaterSpeed.z = 0.2f;
- m_bOnGround = false;
- break;
- case Z_MINUS:
- m_WaterSpeed.z = -0.2f;
- m_bOnGround = false;
- break;
-
- default:
+ switch(WaterDir)
+ {
+ case X_PLUS:
+ m_WaterSpeed.x = 0.2f;
+ m_bOnGround = false;
break;
- }
+ case X_MINUS:
+ m_WaterSpeed.x = -0.2f;
+ m_bOnGround = false;
+ break;
+ case Z_PLUS:
+ m_WaterSpeed.z = 0.2f;
+ m_bOnGround = false;
+ break;
+ case Z_MINUS:
+ m_WaterSpeed.z = -0.2f;
+ m_bOnGround = false;
+ break;
+
+ default:
+ break;
+ }
- if (fabs(m_WaterSpeed.x) < 0.05)
- {
- m_WaterSpeed.x = 0;
- }
+ if (fabs(m_WaterSpeed.x) < 0.05)
+ {
+ m_WaterSpeed.x = 0;
+ }
- if (fabs(m_WaterSpeed.z) < 0.05)
- {
- m_WaterSpeed.z = 0;
- }
+ if (fabs(m_WaterSpeed.z) < 0.05)
+ {
+ m_WaterSpeed.z = 0;
+ }
- NextSpeed += m_WaterSpeed;
+ NextSpeed += m_WaterSpeed;
- if( NextSpeed.SqrLength() > 0.f )
+ if( NextSpeed.SqrLength() > 0.f )
+ {
+ cTracer Tracer( GetWorld() );
+ int Ret = Tracer.Trace( NextPos, NextSpeed, 2 );
+ if( Ret ) // Oh noez! we hit something
{
- cTracer Tracer( GetWorld() );
- int Ret = Tracer.Trace( NextPos, NextSpeed, 2 );
- if( Ret ) // Oh noez! we hit something
+ // Set to hit position
+ if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
{
- // Set to hit position
- if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
+ if( Ret == 1 )
{
- if( Ret == 1 )
+ if( Tracer.HitNormal.x != 0.f ) NextSpeed.x = 0.f;
+ if( Tracer.HitNormal.y != 0.f ) NextSpeed.y = 0.f;
+ if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 0.f;
+
+ if( Tracer.HitNormal.y > 0 ) // means on ground
{
- if( Tracer.HitNormal.x != 0.f ) NextSpeed.x = 0.f;
- if( Tracer.HitNormal.y != 0.f ) NextSpeed.y = 0.f;
- if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 0.f;
-
- if( Tracer.HitNormal.y > 0 ) // means on ground
- {
- m_bOnGround = true;
- }
+ m_bOnGround = true;
}
- NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
- NextPos.x += Tracer.HitNormal.x * 0.3f;
- NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
- NextPos.z += Tracer.HitNormal.z * 0.3f;
- }
- else
- {
- NextPos += (NextSpeed * a_Dt);
}
+ NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
+ NextPos.x += Tracer.HitNormal.x * 0.3f;
+ NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
+ NextPos.z += Tracer.HitNormal.z * 0.3f;
}
else
{
- // We didn't hit anything, so move =]
NextPos += (NextSpeed * a_Dt);
}
}
- BlockX = (int) floor(NextPos.x);
- BlockZ = (int) floor(NextPos.z);
- NextChunk = NextChunk->GetNeighborChunk(BlockX,BlockZ);
- // See if we can commit our changes. If not, we will discard them.
- if (NextChunk != NULL)
+ else
{
- if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
- if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
- if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
- if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
- if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
- if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
+ // We didn't hit anything, so move =]
+ NextPos += (NextSpeed * a_Dt);
}
}
+
+ BlockX = (int) floor(NextPos.x);
+ BlockZ = (int) floor(NextPos.z);
+
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
+ // See if we can commit our changes. If not, we will discard them.
+ if (NextChunk != NULL)
+ {
+ if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
+ if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
+ if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
+ if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
+ if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
+ if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
+ }
}
@@ -815,14 +821,13 @@ void cEntity::TickBurning(cChunk & a_Chunk)
{
int RelX = x;
int RelZ = z;
- cChunk * CurChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ);
- if (CurChunk == NULL)
- {
- continue;
- }
+
for (int y = MinY; y <= MaxY; y++)
{
- switch (CurChunk->GetBlock(RelX, y, RelZ))
+ BLOCKTYPE Block;
+ a_Chunk.UnboundedRelGetBlockType(RelX, y, RelZ, Block);
+
+ switch (Block)
{
case E_BLOCK_FIRE:
{
@@ -922,7 +927,7 @@ void cEntity::TickInVoid(cChunk & a_Chunk)
void cEntity::SetSwimState(cChunk & a_Chunk)
{
- int RelY = (int)floor(m_LastPosY + 0.1);
+ int RelY = (int)floor(GetPosY() + 0.1);
if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
{
m_IsSwimming = false;
@@ -931,11 +936,10 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
}
BLOCKTYPE BlockIn;
- int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width;
- int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width;
+ int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
+ int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
// Check if the player is swimming:
- // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk
if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
{
// This sometimes happens on Linux machines