Exception in AI library while calling goToNextWaypoint()

Not sure if i have done something wrong here but looking at the source code it seems like it will always throw an exception when it reaches the end of the waypoint list?
[java]Sep 21, 2013 3:33:14 PM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at com.jme3.ai.navmesh.NavMeshPathfinder.goToNextWaypoint(NavMeshPathfinder.java:188)
at com.jme3.ai.navmesh.NavMeshPathfinder.goToNextWaypoint(NavMeshPathfinder.java:183)
at Map.Pathing.PathFinding$PathFollowingEntity.update(PathFinding.java:222)[/java]

The line in my code at 222 is just calling
navi.goToNextWaypoint();

which is currently at the end of the list as its reached the last waypoint

The code from the AI library
[java]public void goToNextWaypoint(DebugInfo debugInfo) {
int from = getPath().getWaypoints().indexOf(nextWaypoint);
nextWaypoint = getPath().getWaypoints().get(from + 1);
//nextWaypoint = path.getFurthestVisibleWayPoint(nextWaypoint, debugInfo);//path.getOptimalVisibleWayPoint(nextWaypoint);
int to = getPath().getWaypoints().indexOf(nextWaypoint);
//Vector3f waypt = nextWaypoint.getPosition();
//currentPos3d.setX(waypt.getX());
//currentPos3d.setZ(waypt.getZ());
//currentPos.set(waypt.getX(), waypt.getZ());
currentCell = nextWaypoint.getCell();
//System.out.println("Going from WP idx “+from+” to "+to);
}[/java]
just tries to increment to the next waypoint with no check to see if it exists or has reached the limit of the list

I think there should be a check here before the 2nd line something like
[java]
if(getPath().getWaypoints().size() < from +1)
{
nextWaypoint = getPath().getWaypoints().get(from + 1);
}

I am currently using this in an update loop
[java]
Waypoint waypoint = navi.getNextWaypoint();
Vector3f vector = waypoint.getPosition().subtract(GetPositionFromEntity(entity));
if(vector.length() > 1)
{
mc.direction = vector;
}
else
{
navi.goToNextWaypoint();
}
[/java]
If i am using it incorrectly id love to know basically it will always call goToNextWaypoint at the end of the path once
I can perform a check outside the system to see if its safe for it to internally increment but that seems quite dodgy the class should be responsible for safely incrementing its own internal state surely?

Cheers

nextWaypoint = getPath().getWaypoints().get(from + 1);

Thats the problem. The arraylist is the length of 4, but its index starts at 0, so when ur code is calling 4, its actually calling element 5, which dose not exist. So you should remove that +1 completely, and do a boolean checking if the list is empty. And also check if the length “from” is exactly the length of the array or smaller by 1 increment. Also, i’d suggest using a Queue, than an array list.

1 Like

Thank you for confirming the issue but i think I wasn’t clear enough the problem is in the AI library not in my code
Calling goToNextWaypoint() will eventually throw an exception

I was reporting the issue and mentioning that in my opinion when calling an increment function it should be safe and not throw exceptions.

If I was getting a list back and incrementing it myself no issues there with exceptions getting thrown that would be my own fault but if a enclosed class is throwing exceptions when incrementing its own internal variables that seems to be a little dodgy/careless

Unless the function is called goToNextWaypointOrThrowException

The last code part of my suggestion and my current code got mixed in together and for some reason I can’t edit my posts anymore (EDIT: apparently you can’t edit the first post in a topic but follow on ones are ok, weird) so I couldn’t correct it

It was meant to say

I think the code should include an out of bounds check before incrementing like so;
[java]if(getPath().getWaypoints().size() < from +1)
{
nextWaypoint = getPath().getWaypoints().get(from + 1);
}[/java]

Then it was meant to show that i am using the code as it was seemingly designed to be used like so in an update loop
[java]Waypoint waypoint = navi.getNextWaypoint();
Vector3f vector = waypoint.getPosition().subtract(GetPositionFromEntity(entity));
if(vector.length() > 1)
{
mc.direction = vector;
}
else
{
navi.goToNextWaypoint();
}[/java]
Hope that clears it up :wink: