public void setMobLimit(final int initialLimit, final int addPerPlayer, final int largestLimit) {
   this.mobLimit =
       world ->
           Math.min(
               largestLimit,
               initialLimit + EntitySelector.players(world, area.toAABB()).size() * addPerPlayer);
 }
  @Override
  public void tick(World world, NBTCompound nbt) {
    if (++tickLimiter > tickRate) {
      tickLimiter = 0;

      List<EntityLiving> mobs = EntitySelector.mobs(world, area.toAABB());
      if (mobs.size() >= mobLimit.applyAsInt(world)) return;

      final Map<Class<? extends EntityLiving>, Integer> mobCounts = new HashMap<>(4);
      final boolean isPeaceful = world.difficultySetting == EnumDifficulty.PEACEFUL;

      for (int attempt = 0; attempt < attemptsPerTick; attempt++) {
        final SpawnEntry<? extends EntityLiving> entry = spawnEntries.getRandomItem(world.rand);
        final Class<? extends EntityLiving> mobClass = entry.getMobClass();

        if (!isPeaceful || !entry.isHostile) {
          int limit = mobClassLimit.get(mobClass);

          if (limit == 0
              || mobCounts.computeIfAbsent(
                      mobClass,
                      cls ->
                          (int)
                              mobs.stream().filter(entity -> entity.getClass() == mobClass).count())
                  < limit) {
            entry.trySpawn(world, attemptsPerMob);
          }
        }
      }
    }
  }
  @Override
  protected EntityLivingBase findNewTarget() {
    double maxDist = getTargetDistance();

    List<T> entities =
        EntitySelector.type(
            taskOwner.worldObj,
            targetClass,
            taskOwner.boundingBox.expand(maxDist, maxDist * 0.5D, maxDist));

    Stream<T> stream =
        entities
            .stream()
            .filter(entity -> entity.getDistanceSqToEntity(taskOwner) <= maxDist * maxDist);
    if (predicate != null) stream = stream.filter(predicate);

    entities = stream.collect(Collectors.toList());
    if (entities.isEmpty()) return null;

    return entities.get(taskOwner.worldObj.rand.nextInt(entities.size()));
  }