Skip to content

Commit

Permalink
Pathing improvement (#10148)
Browse files Browse the repository at this point in the history
Prefer going up when pathing underwater
Fix a crash when tracking
  • Loading branch information
Raycoms authored Aug 22, 2024
1 parent bb16d07 commit 9bc7f4c
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public AbstractAdvancedPathNavigate getNavigation()
this.navigation = newNavigator;
newNavigator.setSwimSpeedFactor(getSwimSpeedFactor());
newNavigator.setSpeedModifier(0.5);
newNavigator.getPathingOptions().withStartSwimCost(2.5D).withSwimCost(1.0D).withCanEnterDoors(true).withDropCost(1D).withJumpCost(1D).withWalkUnderWater(true).withNonLadderClimbableCost(1D).setPassDanger(true);
newNavigator.getPathingOptions().withStartSwimCost(0.0D).withSwimCost(0.0D).withDivingCost(0.0D).withCanEnterDoors(true).withDropCost(0.0D).withJumpCost(0.0D).withWalkUnderWater(true).withNonLadderClimbableCost(0.0D).setPassDanger(true);
PathingStuckHandler stuckHandler = PathingStuckHandler.createStuckHandler()
.withTakeDamageOnStuck(0.4f)
.withBuildLeafBridges()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ public static boolean isWater(@NotNull final BlockGetter world, final BlockPos p
FluidState fluidState = pFluidState;
if (fluidState == null)
{
fluidState = world.getFluidState(pos);
fluidState = state.getFluidState();
}

if (fluidState == empty || fluidState.isEmpty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ public class PathingOptions
*/
public double walkInShapesCost = 2D;

/**
* Cost to dive (head underwater).
*/
public double divingCost = 4D;

/**
* Factor multiplied to the small random base cost of values, increases this increases the paths randomness/volatilty. Set to 0 to disable rng.
*/
Expand Down Expand Up @@ -234,6 +239,12 @@ public PathingOptions withNonLadderClimbableCost(final double nonLadderClimbable
return this;
}

public PathingOptions withDivingCost(final double divingCost)
{
this.divingCost = divingCost;
return this;
}

/**
* Sets swimming ability
*
Expand Down Expand Up @@ -284,6 +295,8 @@ public void importFrom(final PathingOptions pathingOptions)
swimCostEnter = pathingOptions.swimCostEnter;
traverseToggleAbleCost = pathingOptions.traverseToggleAbleCost;
nonLadderClimbableCost = pathingOptions.nonLadderClimbableCost;
divingCost = pathingOptions.divingCost;

canUseRails = pathingOptions.canUseRails;
canSwim = pathingOptions.canSwim;
enterDoors = pathingOptions.enterDoors;
Expand All @@ -294,5 +307,4 @@ public void importFrom(final PathingOptions pathingOptions)
walkUnderWater = pathingOptions.walkUnderWater;
canDrop = pathingOptions.canDrop;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,11 @@ protected void followThePath()
boolean isTracking = PathfindingUtils.trackingMap.containsValue(ourEntity.getUUID());

HashSet<BlockPos> reached = null;
if (isTracking)
{
reached = new HashSet<>();
}

// Look at multiple points, incase we're too fast
for (int i = this.path.getNextNodeIndex(); i < Math.min(this.path.getNodeCount(), this.path.getNextNodeIndex() + 4); i++)
{
Expand All @@ -979,17 +984,13 @@ protected void followThePath()

if (isTracking)
{
if (reached == null)
{
reached = new HashSet<>();
}
final Node point = path.getNode(i);
reached.add(new BlockPos(point.x, point.y, point.z));
}
}
}

if (isTracking && reached != null)
if (isTracking)
{
PathfindingUtils.syncDebugReachedPositions(reached, ourEntity);
reached.clear();
Expand Down Expand Up @@ -1033,7 +1034,7 @@ else if (isTracking)
}
}

if (isTracking && reached != null)
if (isTracking)
{
PathfindingUtils.syncDebugReachedPositions(reached, ourEntity);
reached.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -733,19 +733,22 @@ else if (!node.isCornerNode() && newY - node.y < 0 && (dX != 0 || dZ != 0) &&
}
}

final boolean isSwimming = calculateSwimming(world, nextX, nextY, nextZ, nextNode);
final BlockState aboveState = cachedBlockLookup.getBlockState(nextX, nextY + 1, nextZ);
final BlockState state = cachedBlockLookup.getBlockState(nextX, nextY, nextZ);
final BlockState belowState = cachedBlockLookup.getBlockState(nextX, nextY - 1, nextZ);

final boolean isSwimming = calculateSwimming(belowState, state, aboveState, nextNode);
if (isSwimming && !pathingOptions.canSwim())
{
return;
}

final boolean swimStart = isSwimming && !node.isSwimming();
final BlockState state = cachedBlockLookup.getBlockState(nextX, nextY, nextZ);
final BlockState belowState = cachedBlockLookup.getBlockState(nextX, nextY - 1, nextZ);
final boolean onRoad = WorkerUtil.isPathBlock(belowState.getBlock());
final boolean onRails = pathingOptions.canUseRails() && (corner ? belowState : state).getBlock() instanceof BaseRailBlock;
final boolean railsExit = !onRails && node != null && node.isOnRails();
final boolean ladder = PathfindingUtils.isLadder(state, pathingOptions);
final boolean isDiving = isSwimming && PathfindingUtils.isWater(world, null, aboveState, null);

double nextCost = 0;
if (!corner)
Expand All @@ -760,7 +763,7 @@ else if (!node.isCornerNode() && newY - node.y < 0 && (dX != 0 || dZ != 0) &&
costFrom = node.parent;
}

nextCost = computeCost(costFrom, dX, dY, dZ, isSwimming, onRoad, onRails, railsExit, swimStart, ladder, state, belowState, nextX, nextY, nextZ);
nextCost = computeCost(costFrom, dX, dY, dZ, isSwimming, isDiving, onRoad, onRails, railsExit, swimStart, ladder, state, belowState, nextX, nextY, nextZ);
nextCost = modifyCost(nextCost, costFrom, swimStart, isSwimming, nextX, nextY, nextZ, state, belowState);

if (nextCost > maxCost)
Expand Down Expand Up @@ -884,6 +887,7 @@ protected double computeCost(
final MNode parent, final int dX, final int dY, final int dZ,
final boolean isSwimming,
final boolean onPath,
final boolean isDiving,
final boolean onRails,
final boolean railsExit,
final boolean swimStart,
Expand All @@ -893,13 +897,16 @@ protected double computeCost(
{
double cost = 1;

if (onPath)
if (!isSwimming)
{
cost *= pathingOptions.onPathCost;
}
if (onRails)
{
cost *= pathingOptions.onRailCost;
if (onPath)
{
cost *= pathingOptions.onPathCost;
}
if (onRails)
{
cost *= pathingOptions.onRailCost;
}
}

if (pathingOptions.randomnessFactor > 0.0d)
Expand All @@ -912,15 +919,18 @@ protected double computeCost(
cost += pathingOptions.caveAirCost;
}

if (dY != 0 && !(ladder && parent.isLadder()) && !(Math.abs(dY) == 1 && below.is(BlockTags.STAIRS)))
if (!isDiving)
{
if (dY > 0)
if (dY != 0 && !(ladder && parent.isLadder()) && !(Math.abs(dY) == 1 && below.is(BlockTags.STAIRS)))
{
cost += pathingOptions.jumpCost;
}
else if (pathingOptions.dropCost != 0)
{
cost += pathingOptions.dropCost * Math.abs(dY * dY * dY);
if (dY > 0)
{
cost += pathingOptions.jumpCost;
}
else if (pathingOptions.dropCost != 0)
{
cost += pathingOptions.dropCost * Math.abs(dY * dY * dY);
}
}
}

Expand All @@ -943,7 +953,7 @@ else if (!ShapeUtil.isEmpty(state.getCollisionShape(cachedBlockLookup, tempWorld
cost += pathingOptions.railsExitCost;
}

if (ladder && !parent.isLadder() && !(state.getBlock() instanceof LadderBlock))
if (!isDiving && ladder && !parent.isLadder() && !(state.getBlock() instanceof LadderBlock))
{
cost += pathingOptions.nonLadderClimbableCost;
}
Expand All @@ -958,6 +968,10 @@ else if (!ShapeUtil.isEmpty(state.getCollisionShape(cachedBlockLookup, tempWorld
{
cost += pathingOptions.swimCost;
}
if (isDiving)
{
cost += pathingOptions.divingCost;
}
}

return cost;
Expand Down Expand Up @@ -1531,9 +1545,16 @@ private boolean canLeaveBlock(final int x, final int y, final int z, final MNode
return true;
}

private boolean calculateSwimming(@NotNull final LevelReader world, final int x, final int y, final int z, @Nullable final MNode node)
private boolean calculateSwimming(final BlockState below, final BlockState state, final BlockState above, @Nullable final MNode node)
{
return (node == null) ? PathfindingUtils.isWater(world, tempWorldPos.set(x, y - 1, z)) : node.isSwimming();
if (node != null)
{
return node.isSwimming();
}

return PathfindingUtils.isWater(cachedBlockLookup, null, below,null)
|| PathfindingUtils.isWater(cachedBlockLookup, null, state,null)
|| PathfindingUtils.isWater(cachedBlockLookup, null, above,null);
}

/**
Expand Down

0 comments on commit 9bc7f4c

Please sign in to comment.