This would be a bit cleaner, allowing for types other than just NPC, and filters other than just entity name:
public <T extends Entity> Optional<T> closestToPosition(final Position position, final List<T> entities) {
return entities.stream().min(Comparator.comparingInt(e -> position.distance(e.getPosition())));
}
Example Usage:
Position pos = new Position(1, 2, 3);
Optional<NPC> rat = closestToPosition(pos, getNpcs().filter(new NameFilter<>("Rat")));
Note that `position.distance()` is the *straight line* distance, it does not take into account any obstacles. This doesn't matter in your specific use-case, but if you wanted to account for it, then you should use getMap().realDistance(). For example:
public <T extends Entity> Optional<T> closestToPosition(final Position position, final List<T> entities) {
return entities.stream().min(Comparator.comparingInt(e -> getMap().realDistance(position, e.getPosition())));
}
Or you can support both options using:
public <T extends Entity> Optional<T> closestToPosition(final Position position, final List<T> entities, final boolean realDistance) {
final ToIntFunction<T> distanceFunc = (T e) -> (
realDistance ? getMap().realDistance(position, e.getPosition())
: position.distance(e.getPosition())
);
return entities.stream().min(Comparator.comparingInt(distanceFunc));
}
If you want to include further filtering abilities within the helper function itself, that can also be achieved using:
public <T extends Entity> Optional<T> closestToPosition(final Position position, final List<T> entities, final boolean realDistance, final Filter<T>... entityFilter) {
final ToIntFunction<T> distanceFunc = (T e) -> (
realDistance ? getMap().realDistance(position, e.getPosition())
: position.distance(e.getPosition())
);
final Predicate<T> aggregatedEntityFilter = e -> Stream.of(entityFilter).allMatch(filter -> filter.match(e));
return entities.stream().filter(aggregatedEntityFilter).min(Comparator.comparingInt(distanceFunc));
}
Example usage:
Position pos = new Position(1, 2, 3);
Optional<NPC> rat = closestToPosition(pos, getNpcs().getAll(), true, new NameFilter<>("Rat"));