summaryrefslogtreecommitdiffstats
path: root/src/Mobs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Mobs/Path.cpp2
-rw-r--r--src/Mobs/PathFinder.cpp74
2 files changed, 40 insertions, 36 deletions
diff --git a/src/Mobs/Path.cpp b/src/Mobs/Path.cpp
index e9c4e6ca7..05ccd6c39 100644
--- a/src/Mobs/Path.cpp
+++ b/src/Mobs/Path.cpp
@@ -480,7 +480,7 @@ void cPath::FillCellAttributes(cPathCell & a_Cell)
ASSERT(m_Chunk != nullptr);
- if (!cChunkDef::IsValidHeight(Location.y))
+ if (!cChunkDef::IsValidHeight(Location))
{
// Players can't build outside the game height, so it must be air
a_Cell.m_IsSolid = false;
diff --git a/src/Mobs/PathFinder.cpp b/src/Mobs/PathFinder.cpp
index bcc48d80e..260044f3b 100644
--- a/src/Mobs/PathFinder.cpp
+++ b/src/Mobs/PathFinder.cpp
@@ -185,74 +185,78 @@ bool cPathFinder::EnsureProperPoint(Vector3d & a_Vector, cChunk & a_Chunk)
return false;
}
- int RelX = FloorC(a_Vector.x) - Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = FloorC(a_Vector.z) - Chunk->GetPosZ() * cChunkDef::Width;
-
// If destination in the air, first try to go 1 block north, or east, or west.
// This fixes the player leaning issue.
// If that failed, we instead go down to the lowest air block.
- int YBelowUs = FloorC(a_Vector.y) - 1;
- if (!cChunkDef::IsValidHeight(YBelowUs))
+ auto Below = a_Vector.Floor().addedY(-1);
+ if (!cChunkDef::IsValidHeight(Below))
{
return false;
}
- Chunk->GetBlockTypeMeta(RelX, YBelowUs, RelZ, BlockType, BlockMeta);
+ auto BelowRel = cChunkDef::AbsoluteToRelative(Below);
+
+ Chunk->GetBlockTypeMeta(BelowRel, BlockType, BlockMeta);
if (!(IsWaterOrSolid(BlockType)))
{
+ constexpr std::array<Vector3i, 8> Offsets =
+ {
+ {
+ {-1, 0, 0},
+ {1, 0, 0},
+ {0, 0, -1},
+ {0, 0, 1},
+ {-1, 0, -1},
+ {-1, 0, 1},
+ {1, 0, -1},
+ {1, 0, 1},
+ }
+ };
+
+ // Looks for a neighbouring block one block in x or z direction that is water or solid.
bool InTheAir = true;
- int x, z;
- for (z = -1; z <= 1; ++z)
+ for (const auto & Offset : Offsets)
{
- for (x = -1; x <= 1; ++x)
+ auto InspectPos = Below + Offset;
+ Chunk = a_Chunk.GetNeighborChunk(InspectPos.x, InspectPos.z);
+ if ((Chunk == nullptr) || !Chunk->IsValid())
{
- if ((x == 0) && (z == 0))
- {
- continue;
- }
- Chunk = a_Chunk.GetNeighborChunk(FloorC(a_Vector.x+x), FloorC(a_Vector.z+z));
- if ((Chunk == nullptr) || !Chunk->IsValid())
- {
- return false;
- }
- RelX = FloorC(a_Vector.x+x) - Chunk->GetPosX() * cChunkDef::Width;
- RelZ = FloorC(a_Vector.z+z) - Chunk->GetPosZ() * cChunkDef::Width;
- Chunk->GetBlockTypeMeta(RelX, YBelowUs, RelZ, BlockType, BlockMeta);
- if (IsWaterOrSolid((BlockType)))
- {
- a_Vector.x += x;
- a_Vector.z += z;
- InTheAir = false;
- goto breakBothLoops;
- }
+ return false;
+ }
+ auto InspectRel = cChunkDef::AbsoluteToRelative(InspectPos);
+ Chunk->GetBlockTypeMeta(InspectRel, BlockType, BlockMeta);
+ if (IsWaterOrSolid((BlockType)))
+ {
+ BelowRel = InspectRel;
+ InTheAir = false;
+ break;
}
}
- breakBothLoops:
// Go down to the lowest air block.
if (InTheAir)
{
- while (a_Vector.y > 0)
+ while (cChunkDef::IsValidHeight(a_Vector.addedY(-1)))
{
- Chunk->GetBlockTypeMeta(RelX, FloorC(a_Vector.y) - 1, RelZ, BlockType, BlockMeta);
+ Chunk->GetBlockTypeMeta(BelowRel.addedY(-1), BlockType, BlockMeta);
if (IsWaterOrSolid(BlockType))
{
break;
}
- a_Vector.y -= 1;
+ BelowRel.y -= 1;
}
}
}
// If destination in water or solid, go up to the first air block.
- while (a_Vector.y < cChunkDef::Height)
+ while (BelowRel.y < cChunkDef::Height)
{
- Chunk->GetBlockTypeMeta(RelX, FloorC(a_Vector.y), RelZ, BlockType, BlockMeta);
+ Chunk->GetBlockTypeMeta(BelowRel, BlockType, BlockMeta);
if (!IsWaterOrSolid(BlockType))
{
break;
}
- a_Vector.y += 1;
+ BelowRel.y += 1;
}
return true;