summaryrefslogtreecommitdiffstats
path: root/src/Mobs/Path.h
diff options
context:
space:
mode:
authorSafwat Halaby <SafwatHalaby@users.noreply.github.com>2015-12-22 06:43:50 +0100
committerSafwat Halaby <SafwatHalaby@users.noreply.github.com>2015-12-24 05:20:16 +0100
commitdfeced18b2397234340b94fe0ba61cc567c9cfc5 (patch)
treebc50fe2d4f011c05eedd389ab4924747d0085baf /src/Mobs/Path.h
parentMerge pull request #2811 from cuberite/isblockfence (diff)
downloadcuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.tar
cuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.tar.gz
cuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.tar.bz2
cuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.tar.lz
cuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.tar.xz
cuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.tar.zst
cuberite-dfeced18b2397234340b94fe0ba61cc567c9cfc5.zip
Diffstat (limited to 'src/Mobs/Path.h')
-rw-r--r--src/Mobs/Path.h64
1 files changed, 39 insertions, 25 deletions
diff --git a/src/Mobs/Path.h b/src/Mobs/Path.h
index ac71968bd..c6f47ada3 100644
--- a/src/Mobs/Path.h
+++ b/src/Mobs/Path.h
@@ -7,6 +7,7 @@ enum class ePathFinderStatus;
class cPath;
*/
+
#include "../FastRandom.h"
#ifdef COMPILING_PATHFIND_DEBUGGER
/* Note: the COMPILING_PATHFIND_DEBUGGER flag is used by Native / WiseOldMan95 to debug
@@ -19,22 +20,40 @@ class cPath;
//fwd: ../Chunk.h
class cChunk;
+
/* Various little structs and classes */
enum class ePathFinderStatus {CALCULATING, PATH_FOUND, PATH_NOT_FOUND, NEARBY_FOUND};
enum class eCellStatus {OPENLIST, CLOSEDLIST, NOLIST};
+/** The pathfinder has 3 types of cells (cPathCell).
+1 - empty. m_IsSolid is false, m_IsSpecial is false. Air cells are always traversable by A*.
+2 - occupied / solid. m_IsSolid is true, m_IsSpecial is false. Air cells are never traversable by A*.
+3 - Special. m_IsSolid is true, m_IsSpecial is true. These cells are special: They may either behave as empty
+or as occupied / solid, depending on the mob's direction of movement. For instance, an airblock above a fence is a special cell,
+because when mobs attempt to travel to it by jumping, it acts as a solid. But when mobs fall and land on top of a fence,
+it acts as air. Special cells include: Doors, ladders, trapdoors, water, gates.
+
+The main function which handles special blocks is SpecialIsSolidFromThisDirection.
+This function receives a BlockType, a meta, and a direction of travel,
+then it uses those 3 parameters to decide whether the special block should behave as a solid or as air in this
+particular direction of travel.
+
+Currently, only fences and water are handled properly. The function always returns "true" (meaning: treat as occuiped/solid) for
+the rest of the blocks. This will be fixed once the physics engine issues are fixed. */
struct cPathCell
{
Vector3i m_Location; // Location of the cell in the world.
int m_F, m_G, m_H; // F, G, H as defined in regular A*.
eCellStatus m_Status; // Which list is the cell in? Either non, open, or closed.
cPathCell * m_Parent; // Cell's parent, as defined in regular A*.
- bool m_IsSolid; // Is the cell an air or a solid? Partial solids are currently considered solids.
+ bool m_IsSolid; // Is the cell an air or a solid? Partial solids are considered solids. If m_IsSpecial is true, this is always true.
+ bool m_IsSpecial; // The cell is special - it acts as "solid" or "air" depending on direction, e.g. door or top of fence.
+ BLOCKTYPE m_BlockType;
+ NIBBLETYPE m_BlockMeta;
};
-
class compareHeuristics
{
public:
@@ -48,32 +67,22 @@ public:
class cPath
{
public:
- /** Creates a pathfinder instance. A Mob will probably need a single pathfinder instance for its entire life.
-
- Note that if you have a man-sized mob (1x1x2, zombies, etc), you are advised to call this function without parameters
- because the declaration might change in later version of the pathFinder, and a parameter-less call always assumes a man-sized mob.
+ /** Creates a pathfinder instance.
+ After calling this, you are expected to call CalculationStep() once per tick or once per several ticks
+ until it returns something other than CALCULATING.
- If your mob is not man-sized, you are advised to use cPath(width, height), this would be compatible with future versions,
- but please be aware that as of now those parameters will be ignored and your mob will be assumed to be man sized.
-
- @param a_BoundingBoxWidth the character's boundingbox width in blocks. Currently the parameter is ignored and 1 is assumed.
- @param a_BoundingBoxHeight the character's boundingbox width in blocks. Currently the parameter is ignored and 2 is assumed.
- @param a_MaxUp the character's max jump height in blocks. Currently the parameter is ignored and 1 is assumed.
- @param a_MaxDown How far is the character willing to fall? Currently the parameter is ignored and 1 is assumed. */
- /** Attempts to find a path starting from source to destination.
- After calling this, you are expected to call Step() once per tick or once per several ticks until it returns true. You should then call getPath() to obtain the path.
- Calling this before a path is found resets the current path and starts another search.
@param a_StartingPoint The function expects this position to be the lowest block the mob is in, a rule of thumb: "The block where the Zombie's knees are at".
@param a_EndingPoint "The block where the Zombie's knees want to be".
- @param a_MaxSteps The maximum steps before giving up. */
+ @param a_MaxSteps The maximum steps before giving up.
+ @param a_BoundingBoxWidth the character's boundingbox width in blocks. Currently the parameter is ignored and 1 is assumed.
+ @param a_BoundingBoxHeight the character's boundingbox width in blocks. Currently the parameter is ignored and 2 is assumed. */
cPath(
cChunk & a_Chunk,
const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps,
- double a_BoundingBoxWidth, double a_BoundingBoxHeight,
- int a_MaxUp = 1, int a_MaxDown = 1
+ double a_BoundingBoxWidth, double a_BoundingBoxHeight
);
- /** Creates a dummy path which does nothing except returning false when isValid is called. */
+ /** Creates an invalid path which is not usable. You shouldn't call any method other than isValid on such a path. */
cPath();
/** delete default constructors */
@@ -84,9 +93,11 @@ public:
cPath & operator=(cPath && a_other) = delete;
/** Performs part of the path calculation and returns the appropriate status.
+ If PATH_FOUND is returned, the path was found, and you can call query the instance for waypoints via GetNextWayPoint, etc.
If NEARBY_FOUND is returned, it means that the destination is not reachable, but a nearby destination
is reachable. If the user likes the alternative destination, they can call AcceptNearbyPath to treat the path as found,
- and to make consequent calls to step return PATH_FOUND */
+ and to make consequent calls to step return PATH_FOUND
+ If PATH_NOT_FOUND is returned, then no path was found. */
ePathFinderStatus CalculationStep(cChunk & a_Chunk);
/** Called after the PathFinder's step returns NEARBY_FOUND.
@@ -142,7 +153,6 @@ public:
private:
/* General */
- bool IsSolid(const Vector3i & a_Location); // Query our hosting world and ask it if there's a solid at a_location.
bool StepOnce(); // The public version just calls this version * CALCULATIONS_PER_CALL times.
void FinishCalculation(); // Clears the memory used for calculating the path.
void FinishCalculation(ePathFinderStatus a_NewStatus); // Clears the memory used for calculating the path and changes the status.
@@ -152,7 +162,7 @@ private:
/* Openlist and closedlist management */
void OpenListAdd(cPathCell * a_Cell);
cPathCell * OpenListPop();
- bool ProcessIfWalkable(const Vector3i &a_Location, cPathCell * a_Parent, int a_Cost);
+ bool ProcessIfWalkable(const Vector3i & a_Location, cPathCell * a_Source, int a_Cost);
/* Map management */
void ProcessCell(cPathCell * a_Cell, cPathCell * a_Caller, int a_GDelta);
@@ -179,12 +189,16 @@ private:
std::vector<Vector3i> m_PathPoints;
/* Interfacing with the world */
+ void FillCellAttributes(cPathCell & a_Cell); // Query our hosting world and fill the cell with info
cChunk * m_Chunk; // Only valid inside Step()!
bool m_BadChunkFound;
/* High level world queries */
- bool IsWalkable(const Vector3i & a_Location);
- bool BodyFitsIn(const Vector3i & a_Location);
+ bool IsWalkable(const Vector3i & a_Location, const Vector3i & a_Source);
+ bool BodyFitsIn(const Vector3i & a_Location, const Vector3i & a_Source);
+ bool BlockTypeIsSpecial(BLOCKTYPE a_Type);
+ bool BlockTypeIsFence(BLOCKTYPE a_Type); // TODO Perhaps this should be moved to cBlockInfo
+ bool SpecialIsSolidFromThisDirection(BLOCKTYPE a_Type, NIBBLETYPE a_Meta, const Vector3i & a_Direction);
bool HasSolidBelow(const Vector3i & a_Location);
#ifdef COMPILING_PATHFIND_DEBUGGER
#include "../path_irrlicht.cpp"