// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.role.support;

import com.hypixel.hytale.function.predicate.QuadObjectDoublePredicate;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.server.npc.components.SortBufferProviderResource;
import java.util.function.Predicate;
import com.hypixel.hytale.function.consumer.TriConsumer;
import java.util.Set;
import com.hypixel.hytale.function.consumer.QuadConsumer;
import com.hypixel.hytale.function.predicate.QuadPredicate;
import com.hypixel.hytale.common.collection.BucketItem;
import com.hypixel.hytale.function.consumer.DoubleQuadObjectConsumer;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.util.MathUtil;
import javax.annotation.Nullable;
import com.hypixel.hytale.common.collection.BucketItemPool;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import javax.annotation.Nonnull;
import com.hypixel.hytale.component.ComponentAccessor;
import java.util.function.BiPredicate;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.common.collection.BucketList;

public class EntityList extends BucketList<Ref<EntityStore>>
{
    protected static final int BUCKET_COUNT = 6;
    protected static final int BUCKET_DISTANCE_NEAR = 5;
    protected static final int BUCKET_DISTANCE_NEARER = 3;
    protected static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE;
    @Nonnull
    protected final BiPredicate<Ref<EntityStore>, ComponentAccessor<EntityStore>> validator;
    protected IntArrayList bucketRanges;
    protected int maxDistanceUnsorted;
    protected int maxDistanceSorted;
    protected int maxDistanceAvoidance;
    protected int squaredMaxDistanceSorted;
    protected int squaredMaxDistanceAvoidance;
    protected int squaredMaxDistanceUnsorted;
    protected int searchRadius;
    
    public EntityList(@Nullable final BucketItemPool<Ref<EntityStore>> holderPool, @Nonnull final BiPredicate<Ref<EntityStore>, ComponentAccessor<EntityStore>> validator) {
        super(holderPool);
        this.validator = validator;
        this.bucketRanges = new IntArrayList();
    }
    
    public int getMaxDistanceUnsorted() {
        return this.maxDistanceUnsorted;
    }
    
    public int getMaxDistanceSorted() {
        return this.maxDistanceSorted;
    }
    
    public int getMaxDistanceAvoidance() {
        return this.maxDistanceAvoidance;
    }
    
    public int getSearchRadius() {
        return this.searchRadius;
    }
    
    public IntArrayList getBucketRanges() {
        return this.bucketRanges;
    }
    
    @Override
    public void reset() {
        this.maxDistanceUnsorted = 0;
        this.maxDistanceSorted = 0;
        this.maxDistanceAvoidance = 0;
        this.squaredMaxDistanceSorted = 0;
        this.squaredMaxDistanceUnsorted = 0;
        this.squaredMaxDistanceAvoidance = 0;
        this.searchRadius = 0;
        this.squaredMaxDistance = 0;
        super.clear();
        this.bucketRanges.clear();
    }
    
    public int requireDistanceSorted(int value) {
        value = MathUtil.fastCeil((float)value);
        if (this.maxDistanceSorted < value) {
            this.maxDistanceSorted = value;
        }
        BucketList.addBucketDistance(this.bucketRanges, 6, value);
        return value;
    }
    
    public int requireDistanceUnsorted(int value) {
        value = MathUtil.fastCeil((float)value);
        if (this.maxDistanceUnsorted < value) {
            this.maxDistanceUnsorted = value;
        }
        BucketList.addBucketDistance(this.bucketRanges, 6, value);
        return value;
    }
    
    public int requireDistanceAvoidance(int value) {
        value = MathUtil.fastCeil((float)value);
        if (this.maxDistanceAvoidance < value) {
            this.maxDistanceAvoidance = value;
        }
        BucketList.addBucketDistance(this.bucketRanges, 6, value);
        return value;
    }
    
    public void finalizeConfiguration() {
        this.squaredMaxDistanceSorted = this.maxDistanceSorted * this.maxDistanceSorted;
        this.squaredMaxDistanceUnsorted = this.maxDistanceUnsorted * this.maxDistanceUnsorted;
        this.squaredMaxDistanceAvoidance = this.maxDistanceAvoidance * this.maxDistanceAvoidance;
        this.searchRadius = MathUtil.maxValue(this.maxDistanceAvoidance, this.maxDistanceSorted, this.maxDistanceUnsorted);
        this.squaredMaxDistance = this.searchRadius * this.searchRadius;
        if (this.searchRadius == 0) {
            return;
        }
        final int keepRange = (this.maxDistanceAvoidance > 0) ? this.maxDistanceAvoidance : -1;
        if (keepRange > 0) {
            BucketList.addBucketDistance(this.bucketRanges, 6, keepRange);
        }
        if (this.maxDistanceSorted > 3) {
            BucketList.addBucketDistance(this.bucketRanges, 6, 3, keepRange);
            if (this.maxDistanceSorted > 5) {
                BucketList.addBucketDistance(this.bucketRanges, 6, 5, keepRange);
            }
        }
        super.configureWithPreSortedArray(this.bucketRanges.toIntArray());
    }
    
    public void add(@Nonnull final Ref<EntityStore> ref, @Nonnull final Vector3d parentPosition, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
        if (!this.validator.test(ref, commandBuffer)) {
            return;
        }
        final TransformComponent transformComponent = commandBuffer.getComponent(ref, EntityList.TRANSFORM_COMPONENT_TYPE);
        assert transformComponent != null;
        final double distance = parentPosition.distanceSquaredTo(transformComponent.getPosition());
        this.add(ref, distance);
    }
    
    public <T, U, V> void forEachEntity(@Nonnull final DoubleQuadObjectConsumer<Ref<EntityStore>, T, U, V> consumer, final T t, final U u, final V v, final double d, final ComponentAccessor<EntityStore> componentAccessor) {
        for (final Bucket<Ref<EntityStore>> bucket : this.buckets) {
            if (!bucket.isEmpty()) {
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                for (int i = 0, entityHoldersSize = bucket.size(); i < entityHoldersSize; ++i) {
                    final Ref<EntityStore> ref = this.validateEntityRef(entityHolders[i], componentAccessor);
                    if (ref != null) {
                        consumer.accept(d, ref, t, u, v);
                    }
                }
            }
        }
    }
    
    public <T, U, V, R> void forEachEntityUnordered(final double maxDistance, @Nonnull final QuadPredicate<Ref<EntityStore>, T, U, ComponentAccessor<EntityStore>> predicate, @Nonnull final QuadConsumer<Ref<EntityStore>, T, V, R> consumer, final T t, final U u, final V v, final R r, final ComponentAccessor<EntityStore> componentAccessor) {
        final int maxDistanceSquared = (int)(maxDistance * maxDistance);
        for (int endBucket = this.getLastBucketIndex(maxDistanceSquared), i = 0; i <= endBucket; ++i) {
            final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
            if (!bucket.isEmpty()) {
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                if (bucket.isUnsorted()) {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                        if (holder.squaredDistance < maxDistanceSquared) {
                            final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                            if (ref != null && predicate.test(ref, t, u, componentAccessor)) {
                                consumer.accept(ref, t, v, r);
                            }
                        }
                    }
                }
                else {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                        if (holder.squaredDistance >= maxDistanceSquared) {
                            break;
                        }
                        final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                        if (ref != null && predicate.test(ref, t, u, componentAccessor)) {
                            consumer.accept(ref, t, v, r);
                        }
                    }
                }
            }
        }
    }
    
    public <T> void forEachEntityAvoidance(@Nonnull final Set<Ref<EntityStore>> ignoredEntitiesForAvoidance, @Nonnull final TriConsumer<Ref<EntityStore>, T, CommandBuffer<EntityStore>> consumer, final T t, final CommandBuffer<EntityStore> commandBuffer) {
        for (int endBucket = this.getLastBucketIndex(this.squaredMaxDistanceAvoidance), i = 0; i <= endBucket; ++i) {
            final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
            if (!bucket.isEmpty()) {
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                if (bucket.isUnsorted()) {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        if (entityHolder.squaredDistance <= this.squaredMaxDistanceAvoidance) {
                            final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, commandBuffer);
                            if (ref != null && !ignoredEntitiesForAvoidance.contains(ref)) {
                                consumer.accept(ref, t, commandBuffer);
                            }
                        }
                    }
                }
                else {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        if (entityHolder.squaredDistance > this.squaredMaxDistanceAvoidance) {
                            break;
                        }
                        final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, commandBuffer);
                        if (ref != null && !ignoredEntitiesForAvoidance.contains(ref)) {
                            consumer.accept(ref, t, commandBuffer);
                        }
                    }
                }
            }
        }
    }
    
    public <T, U> void forEachEntityAvoidance(@Nonnull final Set<Ref<EntityStore>> ignoredEntitiesForAvoidance, @Nonnull final QuadConsumer<Ref<EntityStore>, T, U, CommandBuffer<EntityStore>> consumer, final T t, final U u, final CommandBuffer<EntityStore> commandBuffer) {
        for (int endBucket = this.getLastBucketIndex(this.squaredMaxDistanceAvoidance), i = 0; i <= endBucket; ++i) {
            final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
            if (!bucket.isEmpty()) {
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                if (bucket.isUnsorted()) {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        if (entityHolder.squaredDistance <= this.squaredMaxDistanceAvoidance) {
                            final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, commandBuffer);
                            if (ref != null && !ignoredEntitiesForAvoidance.contains(ref)) {
                                consumer.accept(ref, t, u, commandBuffer);
                            }
                        }
                    }
                }
                else {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        if (entityHolder.squaredDistance > this.squaredMaxDistanceAvoidance) {
                            break;
                        }
                        final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, commandBuffer);
                        if (ref != null && !ignoredEntitiesForAvoidance.contains(ref)) {
                            consumer.accept(ref, t, u, commandBuffer);
                        }
                    }
                }
            }
        }
    }
    
    public <S, T> int countEntitiesInRange(final double minRange, final double maxRange, final int maxCount, @Nonnull final QuadPredicate<S, Ref<EntityStore>, T, ComponentAccessor<EntityStore>> filter, final S s, final T t, final ComponentAccessor<EntityStore> componentAccessor) {
        final int minRangeSquared = (int)(minRange * minRange);
        final int startBucket = this.getFirstBucketIndex(minRangeSquared);
        if (startBucket < 0) {
            return 0;
        }
        final int maxRangeSquared = (int)(maxRange * maxRange);
        final int endBucket = this.getLastBucketIndex(maxRangeSquared);
        int count = 0;
        for (int i = startBucket; i <= endBucket && count < maxCount; ++i) {
            final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
            if (!bucket.isEmpty()) {
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                if (bucket.isUnsorted()) {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        final double squaredDistance = entityHolder.squaredDistance;
                        if (squaredDistance >= minRangeSquared) {
                            if (squaredDistance < maxRangeSquared) {
                                final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, componentAccessor);
                                if (ref != null && filter.test(s, ref, t, componentAccessor) && ++count >= maxCount) {
                                    return count;
                                }
                            }
                        }
                    }
                }
                else {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        final double squaredDistance = entityHolder.squaredDistance;
                        if (squaredDistance >= minRangeSquared) {
                            if (squaredDistance >= maxRangeSquared) {
                                return count;
                            }
                            final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, componentAccessor);
                            if (ref != null && filter.test(s, ref, t, componentAccessor) && ++count >= maxCount) {
                                return count;
                            }
                        }
                    }
                }
            }
        }
        return count;
    }
    
    @Nullable
    public Ref<EntityStore> getClosestEntityInRange(final double minRange, final double maxRange, @Nonnull final Predicate<Ref<EntityStore>> filter, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final int minRangeSquared = (int)(minRange * minRange);
        final int startBucket = this.getFirstBucketIndex(minRangeSquared);
        if (startBucket < 0) {
            return null;
        }
        final int maxRangeSquared = (int)(maxRange * maxRange);
        final int endBucket = this.getLastBucketIndex(maxRangeSquared);
        final SortBufferProvider sortBufferProvider = componentAccessor.getResource(SortBufferProviderResource.getResourceType()).getSortBufferProvider();
        for (int i = startBucket; i <= endBucket; ++i) {
            final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
            if (!bucket.isEmpty()) {
                if (bucket.isUnsorted()) {
                    bucket.sort(sortBufferProvider);
                }
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                    final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                    final double squaredDistance = holder.squaredDistance;
                    if (squaredDistance >= minRangeSquared) {
                        if (squaredDistance >= maxRangeSquared) {
                            return null;
                        }
                        final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                        if (ref != null && filter.test(ref)) {
                            return ref;
                        }
                    }
                }
            }
        }
        return null;
    }
    
    @Nullable
    public <S, T> Ref<EntityStore> getClosestEntityInRange(@Nullable final Ref<EntityStore> ignoredEntityReference, final double minRange, final double maxRange, @Nonnull final QuadPredicate<S, Ref<EntityStore>, Role, T> filter, final Role role, final S s, final T t, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final int minRangeSquared = (int)(minRange * minRange);
        final int startBucket = this.getFirstBucketIndex(minRangeSquared);
        if (startBucket < 0) {
            return null;
        }
        final int maxRangeSquared = (int)(maxRange * maxRange);
        final int endBucket = this.getLastBucketIndex(maxRangeSquared);
        final SortBufferProvider sortBufferProvider = componentAccessor.getResource(SortBufferProviderResource.getResourceType()).getSortBufferProvider();
        if (ignoredEntityReference == null) {
            for (int i = startBucket; i <= endBucket; ++i) {
                final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
                if (!bucket.isEmpty()) {
                    if (bucket.isUnsorted()) {
                        bucket.sort(sortBufferProvider);
                    }
                    final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                        final double squaredDistance = holder.squaredDistance;
                        if (squaredDistance >= minRangeSquared) {
                            if (squaredDistance >= maxRangeSquared) {
                                return null;
                            }
                            final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                            if (ref != null && filter.test(s, ref, role, t)) {
                                return ref;
                            }
                        }
                    }
                }
            }
        }
        else {
            for (int i = startBucket; i <= endBucket; ++i) {
                final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
                if (!bucket.isEmpty()) {
                    if (bucket.isUnsorted()) {
                        bucket.sort(sortBufferProvider);
                    }
                    final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                        final double squaredDistance = holder.squaredDistance;
                        if (squaredDistance >= minRangeSquared) {
                            if (squaredDistance >= maxRangeSquared) {
                                return null;
                            }
                            final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                            if (ref != null && !ref.equals(ignoredEntityReference) && filter.test(s, ref, role, t)) {
                                return ref;
                            }
                        }
                    }
                }
            }
        }
        return null;
    }
    
    @Nullable
    public <S, T> Ref<EntityStore> getClosestEntityInRangeProjected(@Nonnull final Ref<EntityStore> parentRef, @Nullable final Ref<EntityStore> ignoredEntityReference, @Nonnull final MotionController motionController, final double minRange, final double maxRange, @Nonnull final QuadPredicate<S, Ref<EntityStore>, Role, T> filter, final Role role, final S s, final T t, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final int minRangeSquared = (int)(minRange * minRange);
        final int startBucket = this.getFirstBucketIndex(minRangeSquared);
        if (startBucket < 0) {
            return null;
        }
        final int maxRangeSquared = (int)(maxRange * maxRange);
        final int endBucket = this.getLastBucketIndex(maxRangeSquared);
        final Vector3d position = componentAccessor.getComponent(parentRef, EntityList.TRANSFORM_COMPONENT_TYPE).getPosition();
        final SortBufferProvider sortBufferProvider = componentAccessor.getResource(SortBufferProviderResource.getResourceType()).getSortBufferProvider();
        if (ignoredEntityReference == null) {
            for (int i = startBucket; i <= endBucket; ++i) {
                final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
                if (!bucket.isEmpty()) {
                    if (bucket.isUnsorted()) {
                        bucket.sort(sortBufferProvider);
                    }
                    final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                        final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                        if (ref != null) {
                            final double squaredDistance = motionController.waypointDistanceSquared(componentAccessor.getComponent(ref, EntityList.TRANSFORM_COMPONENT_TYPE).getPosition(), position);
                            if (squaredDistance >= minRangeSquared) {
                                if (squaredDistance >= maxRangeSquared) {
                                    return null;
                                }
                                if (filter.test(s, ref, role, t)) {
                                    return ref;
                                }
                            }
                        }
                    }
                }
            }
        }
        else {
            for (int i = startBucket; i <= endBucket; ++i) {
                final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
                if (!bucket.isEmpty()) {
                    if (bucket.isUnsorted()) {
                        bucket.sort(sortBufferProvider);
                    }
                    final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> holder = entityHolders[i2];
                        final Ref<EntityStore> ref = this.validateEntityRef(holder, componentAccessor);
                        if (ref != null) {
                            if (!ref.equals(ignoredEntityReference)) {
                                final double squaredDistance = motionController.waypointDistanceSquared(componentAccessor.getComponent(ref, EntityList.TRANSFORM_COMPONENT_TYPE).getPosition(), position);
                                if (squaredDistance >= minRangeSquared) {
                                    if (squaredDistance >= maxRangeSquared) {
                                        return null;
                                    }
                                    if (filter.test(s, ref, role, t)) {
                                        return ref;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }
    
    public <S, T> boolean testAnyEntity(final double maxDistance, @Nonnull final QuadObjectDoublePredicate<S, Ref<EntityStore>, T, ComponentAccessor<EntityStore>> predicate, final S s, final T t, final ComponentAccessor<EntityStore> componentAccessor) {
        return this.testAnyEntityDistanceSquared(maxDistance * maxDistance, predicate, s, t, maxDistance, componentAccessor);
    }
    
    public <S, T> boolean testAnyEntityDistanceSquared(final double maxDistanceSquared, @Nonnull final QuadObjectDoublePredicate<S, Ref<EntityStore>, T, ComponentAccessor<EntityStore>> predicate, final S s, final T t, final ComponentAccessor<EntityStore> componentAccessor) {
        return this.testAnyEntityDistanceSquared(maxDistanceSquared, predicate, s, t, maxDistanceSquared, componentAccessor);
    }
    
    public <S, T> boolean testAnyEntityDistanceSquared(final double maxDistanceSquared, @Nonnull final QuadObjectDoublePredicate<S, Ref<EntityStore>, T, ComponentAccessor<EntityStore>> predicate, final S s, final T t, final double d, final ComponentAccessor<EntityStore> componentAccessor) {
        for (int endBucket = this.getLastBucketIndex((int)maxDistanceSquared), i = 0; i <= endBucket; ++i) {
            final Bucket<Ref<EntityStore>> bucket = (Bucket<Ref<EntityStore>>)this.buckets[i];
            if (!bucket.isEmpty()) {
                final BucketItem<Ref<EntityStore>>[] entityHolders = bucket.getItems();
                if (bucket.isUnsorted()) {
                    for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                        final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                        if (entityHolder.squaredDistance < maxDistanceSquared) {
                            final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, componentAccessor);
                            if (ref != null && predicate.test(s, ref, t, componentAccessor, d)) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
                for (int i2 = 0, entityHoldersSize = bucket.size(); i2 < entityHoldersSize; ++i2) {
                    final BucketItem<Ref<EntityStore>> entityHolder = entityHolders[i2];
                    if (entityHolder.squaredDistance >= maxDistanceSquared) {
                        break;
                    }
                    final Ref<EntityStore> ref = this.validateEntityRef(entityHolder, componentAccessor);
                    if (ref != null && predicate.test(s, ref, t, componentAccessor, d)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    @Nullable
    protected Ref<EntityStore> validateEntityRef(@Nonnull final BucketItem<Ref<EntityStore>> holder, final ComponentAccessor<EntityStore> componentAccessor) {
        final Ref<EntityStore> ref = holder.item;
        return (ref == null || !ref.isValid() || !this.validator.test(ref, componentAccessor)) ? null : ref;
    }
    
    static {
        TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
    }
}
