crwdns141967:0crwdne141967:0

Warning

crwdns141969:0crwdne141969:0

crwdns141971:0:javadoc:crwdnd141971:0:doc:crwdne141971:0

crwdns141973:0crwdne141973:0

import java.util.Comparator;
import java.util.Optional;
import java.util.function.Predicate;

import org.spongepowered.api.GameRegistry;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.ai.task.AITask;
import org.spongepowered.api.entity.ai.task.AITaskType;
import org.spongepowered.api.entity.ai.task.AbstractAITask;
import org.spongepowered.api.entity.living.Agent;

import com.flowpowered.math.vector.Vector3d;
import com.google.common.base.Preconditions;

import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.pathfinding.PathNavigate;

crwdns141975:0crwdne141975:0

private static final double MOVEMENT_SPEED = 1;
private static final double APPROACH_DISTANCE_SQUARED = 2 * 2;
private static final double MAX_DISTANCE_SQUARED = 20 * 20;
private static final float EXECUTION_CHANCE = 0.2F;
private static final int MUTEX_FLAG_MOVE = 1; // Minecraft bit flag

crwdns141977:0:javadoc:crwdnd141977:0:javadoc:crwdne141977:0

public class CreepyCompanionAITask extends AbstractAITask<Agent> {

    private static AITaskType TYPE;

    public static void register(final Object plugin, final GameRegistry gameRegistry) {
        TYPE = gameRegistry
                .registerAITaskType(plugin, "creepy_companion", "CreepyCompanion", CreepyCompanionAITask.class);
    }

    [...]

}

crwdns141979:0crwdne141979:0

@Listener
public void onInitialize(final GameInitializationEvent event) {
    CreepyCompanionAITask.register(this, game.getRegistry());
}

crwdns141981:0crwdne141981:0

  • crwdns141983:0crwdne141983:0

  • crwdns141985:0crwdne141985:0

  • crwdns141987:0crwdne141987:0

  • crwdns141989:0crwdne141989:0

  • crwdns141991:0crwdne141991:0

  • crwdns141993:0crwdne141993:0

  • crwdns141995:0crwdne141995:0

  • crwdns141997:0crwdne141997:0

crwdns141999:0crwdne141999:0

crwdns142001:0crwdne142001:0

crwdns142003:0:javadoc:crwdne142003:0

private final Predicate<Entity> entityFilter;

private Optional<Entity> optTarget;

public CreepyCompanionAITask(final Predicate<Entity> entityFilter) {
    super(TYPE);
    this.entityFilter = Preconditions.checkNotNull(entityFilter);
    ((EntityAIBase) (Object) this).setMutexBits(MUTEX_FLAG_MOVE);
}

crwdns142005:0crwdne142005:0

crwdns142007:0crwdne142007:0

@Override
public boolean canRunConcurrentWith(final AITask<Agent> other) {
    return (((EntityAIBase) (Object) this).getMutexBits() & ((EntityAIBase) other).getMutexBits()) == 0;
}

@Override
public boolean canBeInterrupted() {
    return true;
}

crwdns142009:0crwdne142009:0

  • crwdns142011:0crwdne142011:0

  • crwdns142013:0crwdne142013:0

crwdns142015:0crwdne142015:0

@Override
public boolean shouldUpdate() {
    final Agent owner = getOwner().get();
    if (owner.getRandom().nextFloat() > EXECUTION_CHANCE) {
        return false;
    }

    final Vector3d position = getPositionOf(owner);
    this.optTarget = owner.getWorld()
            .getEntities().stream()
            .filter(this.entityFilter)
            .filter(e -> getPositionOf(e).distanceSquared(position) < MAX_DISTANCE_SQUARED)
            .min(Comparator.comparingDouble(e -> getPositionOf(e).distanceSquared(position)));
    return this.optTarget.isPresent();
}

@Override
public void start() {
    getNavigator().tryMoveToEntityLiving((net.minecraft.entity.Entity) this.optTarget.get(), MOVEMENT_SPEED);
}

crwdns142017:0:javadoc:crwdnd142017:0:javadoc:crwdne142017:0

crwdns142019:0crwdne142019:0

crwdns142021:0crwdne142021:0

crwdns142023:0crwdne142023:0

private Vector3d getPositionOf(final Entity entity) {
    return entity.getLocation().getPosition();
}

private PathNavigate getNavigator() {
    return ((EntityLiving) (getOwner().get())).getNavigator();
}

crwdns142025:0crwdne142025:0

crwdns142027:0crwdne142027:0

@Override
public boolean continueUpdating() {
    if (getNavigator().noPath()) {
        return false;
    }
    if (!this.optTarget.isPresent()) {
        return false;
    }
    final Entity target = this.optTarget.get();
    return getPositionOf(target).distanceSquared(getPositionOf(getOwner().get())) > APPROACH_DISTANCE_SQUARED;
}

@Override
public void update() {
}

@Override
public void reset() {
    getNavigator().clearPath();
    this.optTarget = Optional.empty();
}

crwdns142029:0crwdne142029:0

crwdns142031:0:doc:crwdne142031:0

crwdns142033:0crwdne142033:0