Skip to content

(1.16) Cleanup and optimise AI #4470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
3405b12
Improve the Amphithere AI
Matyrobbrt Apr 30, 2022
31b8cdd
Improve AquaticAI
Matyrobbrt Apr 30, 2022
5011429
Cleanup CockatriceAI
Matyrobbrt Apr 30, 2022
5acf6b5
Fix CyclopsAI
Matyrobbrt Apr 30, 2022
762337b
Improve DeathWormAI
Matyrobbrt Apr 30, 2022
4046d89
Improve DragonAI
Matyrobbrt Apr 30, 2022
c06c524
Improve DreadAI
Matyrobbrt Apr 30, 2022
b4dbe65
Improve GhostAI
Matyrobbrt Apr 30, 2022
2711ab3
Improve AIs
Matyrobbrt Apr 30, 2022
99be250
Improve MyrmexAI
Matyrobbrt Apr 30, 2022
561c618
Clean-up remaining AIs
Matyrobbrt Apr 30, 2022
9d4828e
Implement AABB cache for AmphithereAIFleePlayer
PaintNinja Apr 30, 2022
eca6f24
Optimise and cleanup, reduce unnecessary calcs & checks
PaintNinja Apr 30, 2022
fa417fc
Merge branch 'Alex-the-666:1.16.3' into cleanup-ai
PaintNinja Apr 30, 2022
a280158
Fix NPEs being thrown
Matyrobbrt Apr 30, 2022
a49346c
Change & to &&
Matyrobbrt Apr 30, 2022
a1512f0
WIP AABB caching for TargetItems and other Flee types
PaintNinja Apr 30, 2022
0f41363
Improve the Amphithere AI
Matyrobbrt Apr 30, 2022
c58f2d5
Improve AquaticAI
Matyrobbrt Apr 30, 2022
c91900d
Cleanup CockatriceAI
Matyrobbrt Apr 30, 2022
750acdd
Fix CyclopsAI
Matyrobbrt Apr 30, 2022
f43af09
Improve DeathWormAI
Matyrobbrt Apr 30, 2022
f0b2125
Improve DragonAI
Matyrobbrt Apr 30, 2022
17280ff
Improve DreadAI
Matyrobbrt Apr 30, 2022
ffe6280
Improve GhostAI
Matyrobbrt Apr 30, 2022
bbdd32c
Improve AIs
Matyrobbrt Apr 30, 2022
f6547c0
Improve MyrmexAI
Matyrobbrt Apr 30, 2022
cf14b22
Clean-up remaining AIs
Matyrobbrt Apr 30, 2022
e44ee9c
Implement AABB cache for AmphithereAIFleePlayer
PaintNinja Apr 30, 2022
9228b70
Optimise and cleanup, reduce unnecessary calcs & checks
PaintNinja Apr 30, 2022
018d967
Fix NPEs being thrown
Matyrobbrt Apr 30, 2022
17f7d3d
Change & to &&
Matyrobbrt Apr 30, 2022
0cdc1eb
WIP AABB caching for TargetItems and other Flee types
PaintNinja Apr 30, 2022
2d7d798
Merge branch 'cleanup-ai' of https://github.com/TheModdingInquisition…
Matyrobbrt Apr 30, 2022
e64cb12
Clear targets
Matyrobbrt Apr 30, 2022
ff1b981
Finish list caching for AITargetItems
PaintNinja May 1, 2022
e6c4f60
List caching for all other AI types, style consistency improvements
PaintNinja May 1, 2022
e6fe90b
Merge branch 'Alex-the-666:1.16.3' into cleanup-ai
Matyrobbrt May 2, 2022
b6d2c53
Add missing null check
Matyrobbrt May 2, 2022
7dac0f2
Merge branch 'Alex-the-666:1.16.3' into cleanup-ai
PaintNinja May 2, 2022
387dcbb
Add null check
Matyrobbrt May 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.github.alexthe666.iceandfire.entity.ai;

import net.minecraft.entity.MobEntity;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.minecraft.entity.MobEntity;


/**
* Class to easily list the current tasks/goals of entities and identify potential issues
Expand All @@ -37,12 +35,12 @@ public static void logData(){
if (entity.goalSelector != null) {
List<String> goals = entity.goalSelector.getRunningGoals().map(goal -> goal.getGoal().toString()).collect(Collectors.toList());
if (!goals.isEmpty())
LOGGER.debug(entity.toString() +" - GOALS: " + goals);
LOGGER.debug("{} - GOALS: {}", entity, goals);
}
if (entity.targetSelector != null) {
List<String> targets = entity.targetSelector.getRunningGoals().map(goal -> goal.getGoal().toString()).collect(Collectors.toList());
if (!targets.isEmpty())
LOGGER.debug(entity.toString() +" - TARGET: " + targets);
LOGGER.debug("{} - TARGET: {}", entity, targets);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import net.minecraft.util.Hand;
import net.minecraft.world.World;

import net.minecraft.entity.ai.goal.Goal.Flag;

public class AmphithereAIAttackMelee extends Goal {
protected final int attackInterval = 20;
protected EntityAmphithere attacker;
Expand Down Expand Up @@ -51,6 +49,7 @@ public AmphithereAIAttackMelee(EntityAmphithere amphithere, double speedIn, bool
/**
* Returns whether the Goal should begin execution.
*/
@Override
public boolean shouldExecute() {
LivingEntity LivingEntity = this.attacker.getAttackTarget();
if (!attacker.canMove()) {
Expand Down Expand Up @@ -83,25 +82,27 @@ public boolean shouldExecute() {
/**
* Returns whether an in-progress Goal should continue executing
*/
@Override
public boolean shouldContinueExecuting() {
LivingEntity LivingEntity = this.attacker.getAttackTarget();
LivingEntity living = this.attacker.getAttackTarget();

if (LivingEntity == null) {
if (living == null) {
return false;
} else if (!LivingEntity.isAlive()) {
} else if (!living.isAlive()) {
return false;
} else if (!this.longMemory) {
return !this.attacker.getNavigator().noPath();
} else if (!this.attacker.isWithinHomeDistanceFromPosition(LivingEntity.getPosition())) {
} else if (!this.attacker.isWithinHomeDistanceFromPosition(living.getPosition())) {
return false;
} else {
return !(LivingEntity instanceof PlayerEntity) || !LivingEntity.isSpectator() && !((PlayerEntity) LivingEntity).isCreative();
return !(living instanceof PlayerEntity) || !living.isSpectator() && !((PlayerEntity) living).isCreative();
}
}

/**
* Execute a one shot task or start executing a continuous task
*/
@Override
public void startExecuting() {
if (attacker.isFlying()) {
this.attacker.getMoveHelper().setMoveTo(this.targetX, this.targetY, this.targetZ, 0.1F);
Expand All @@ -114,6 +115,7 @@ public void startExecuting() {
/**
* Reset the task's internal state. Called when this task is interrupted by another one
*/
@Override
public void resetTask() {
LivingEntity LivingEntity = this.attacker.getAttackTarget();

Expand All @@ -124,6 +126,7 @@ public void resetTask() {
this.attacker.getNavigator().clearPath();
}

@Override
public void tick() {
LivingEntity LivingEntity = this.attacker.getAttackTarget();
if (attacker.isFlying()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import net.minecraft.util.EntityPredicates;
import net.minecraft.util.math.vector.Vector3d;

import net.minecraft.entity.ai.goal.Goal.Flag;

public class AmphithereAIFleePlayer extends Goal {
private final double farSpeed;
private final double nearSpeed;
Expand All @@ -31,6 +29,7 @@ public AmphithereAIFleePlayer(EntityAmphithere entityIn, float avoidDistanceIn,
}


@Override
public boolean shouldExecute() {
if (!this.entity.isFlying() && !this.entity.isTamed()) {
List<PlayerEntity> list = this.entity.world.getEntitiesWithinAABB(PlayerEntity.class, this.entity.getBoundingBox().grow(this.avoidDistance, 6D, this.avoidDistance), EntityPredicates.CAN_AI_TARGET);
Expand All @@ -54,18 +53,22 @@ public boolean shouldExecute() {
}
}

@Override
public boolean shouldContinueExecuting() {
return !this.entity.getNavigator().noPath();
}

@Override
public void startExecuting() {
this.entity.getNavigator().setPath(this.path, this.farSpeed);
}

@Override
public void resetTask() {
this.closestLivingEntity = null;
}

@Override
public void tick() {
if (this.entity.getDistanceSq(this.closestLivingEntity) < 49.0D) {
this.entity.getNavigator().setSpeed(this.nearSpeed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;

import net.minecraft.entity.ai.goal.Goal.Flag;

public class AmphithereAIFollowOwner extends Goal {
private final EntityAmphithere ampithere;
private final double followSpeed;
Expand All @@ -34,6 +32,7 @@ public AmphithereAIFollowOwner(EntityAmphithere ampithereIn, double followSpeedI
this.setMutexFlags(EnumSet.of(Flag.MOVE));
}

@Override
public boolean shouldExecute() {
LivingEntity LivingEntity = this.ampithere.getOwner();
if (ampithere.getCommand() != 2) {
Expand All @@ -45,16 +44,18 @@ public boolean shouldExecute() {
return false;
} else if (this.ampithere.isQueuedToSit()) {
return false;
} else if (this.ampithere.getDistanceSq(LivingEntity) < (double) (this.minDist * this.minDist)) {
} else if (this.ampithere.getDistanceSq(LivingEntity) < this.minDist * this.minDist) {
return false;
} else {
this.owner = LivingEntity;
return true;
}
}

@Override
public boolean shouldContinueExecuting() {
return !noPath() && this.ampithere.getDistanceSq(this.owner) > (double) (this.maxDist * this.maxDist) && !this.ampithere.isQueuedToSit();
return !noPath() && this.ampithere.getDistanceSq(this.owner) > this.maxDist * this.maxDist
&& !this.ampithere.isQueuedToSit();
}

private boolean noPath() {
Expand All @@ -65,20 +66,24 @@ private boolean noPath() {
}
}

@Override
public void startExecuting() {
this.timeToRecalcPath = 0;
this.oldWaterCost = this.ampithere.getPathPriority(PathNodeType.WATER);
this.ampithere.setPathPriority(PathNodeType.WATER, 0.0F);
}

@Override
public void resetTask() {
this.owner = null;
this.ampithere.getNavigator().clearPath();
this.ampithere.setPathPriority(PathNodeType.WATER, this.oldWaterCost);
}

@Override
public void tick() {
this.ampithere.getLookController().setLookPositionWithEntity(this.owner, 10.0F, (float) this.ampithere.getVerticalFaceSpeed());
this.ampithere.getLookController().setLookPositionWithEntity(this.owner, 10.0F,
this.ampithere.getVerticalFaceSpeed());

if (!this.ampithere.isQueuedToSit()) {
if (--this.timeToRecalcPath <= 0) {
Expand All @@ -93,7 +98,8 @@ public void tick() {
for (int l = 0; l <= 4; ++l) {
for (int i1 = 0; i1 <= 4; ++i1) {
if ((l < 1 || i1 < 1 || l > 3 || i1 > 3) && this.canTeleportToBlock(new BlockPos(i, j, k))) {
this.ampithere.setLocationAndAngles((float) (i + l) + 0.5F, k, (float) (j + i1) + 0.5F, this.ampithere.rotationYaw, this.ampithere.rotationPitch);
this.ampithere.setLocationAndAngles(i + l + 0.5F, k, j + i1 + 0.5F,
this.ampithere.rotationYaw, this.ampithere.rotationPitch);
ampithere.getNavigator().clearPath();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

public class AmphithereAIHurtByTarget extends HurtByTargetGoal {

public AmphithereAIHurtByTarget(EntityAmphithere amphithere, boolean help, Class[] classes) {
public AmphithereAIHurtByTarget(EntityAmphithere amphithere, boolean help, Class<?>[] classes) {
super(amphithere, classes);
}

protected void setEntityAttackTarget(MobEntity creatureIn, LivingEntity LivingEntityIn) {
protected static void setEntityAttackTarget(MobEntity creatureIn, LivingEntity LivingEntityIn) {
EntityAmphithere amphithere = (EntityAmphithere) creatureIn;
if (amphithere.isTamed() || !(LivingEntityIn instanceof PlayerEntity)) {
amphithere.setAttackTarget(LivingEntityIn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.function.Predicate;

import javax.annotation.Nullable;

import com.github.alexthe666.iceandfire.entity.EntityAmphithere;
import com.google.common.base.Predicate;

import net.minecraft.entity.Entity;
import net.minecraft.entity.MobEntity;
Expand All @@ -18,12 +18,9 @@
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;

import net.minecraft.entity.ai.goal.Goal.Flag;

public class AmphithereAITargetItems<T extends ItemEntity> extends TargetGoal {
protected final DragonAITargetItems.Sorter theNearestAttackableTargetSorter;
protected final Predicate<? super ItemEntity> targetEntitySelector;
private final int targetChance;
protected ItemEntity targetEntity;

public AmphithereAITargetItems(MobEntity creature, boolean checkSight) {
Expand All @@ -36,12 +33,12 @@ public AmphithereAITargetItems(MobEntity creature, boolean checkSight, boolean o

public AmphithereAITargetItems(MobEntity creature, int chance, boolean checkSight, boolean onlyNearby, @Nullable final Predicate<? super T> targetSelector) {
super(creature, checkSight, onlyNearby);
this.targetChance = chance;
this.theNearestAttackableTargetSorter = new DragonAITargetItems.Sorter(creature);
this.targetEntitySelector = new Predicate<ItemEntity>() {

@Override
public boolean apply(@Nullable ItemEntity item) {
return item instanceof ItemEntity && !item.getItem().isEmpty() && item.getItem().getItem() == Items.COCOA_BEANS;
public boolean test(ItemEntity item) {
return !item.getItem().isEmpty() && item.getItem().getItem() == Items.COCOA_BEANS;
}
};
this.setMutexFlags(EnumSet.of(Flag.TARGET));
Expand All @@ -52,11 +49,13 @@ public boolean shouldExecute() {
if (!((EntityAmphithere) this.goalOwner).canMove()) {
return false;
}
//If the target entity already is what we want skip AABB
if (targetEntitySelector.apply(this.targetEntity)){

// If the target entity already is what we want skip AABB
if (targetEntitySelector.test(this.targetEntity)) {
return true;
}
List<ItemEntity> list = this.goalOwner.world.getEntitiesWithinAABB(ItemEntity.class, this.getTargetableArea(this.getTargetDistance()), this.targetEntitySelector);
final List<ItemEntity> list = this.goalOwner.world.getEntitiesWithinAABB(ItemEntity.class,
this.getTargetableArea(this.getTargetDistance()), this.targetEntitySelector);

if (list.isEmpty()) {
return false;
Expand Down Expand Up @@ -110,6 +109,7 @@ public Sorter(Entity theEntityIn) {
this.theEntity = theEntityIn;
}

@Override
public int compare(Entity p_compare_1_, Entity p_compare_2_) {
double d0 = this.theEntity.getDistanceSq(p_compare_1_);
double d1 = this.theEntity.getDistanceSq(p_compare_2_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,11 @@
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.vector.Vector3d;

import net.minecraft.entity.ai.goal.Goal.Flag;

public class AquaticAIFindWaterTarget extends Goal {
protected AquaticAIFindWaterTarget.Sorter fleePosSorter;
private MobEntity mob;
private int range;
private boolean avoidAttacker;

public AquaticAIFindWaterTarget(MobEntity mob, int range, boolean avoidAttacker) {
this.mob = mob;
this.range = range;
this.avoidAttacker = avoidAttacker;
this.setMutexFlags(EnumSet.of(Flag.MOVE));
fleePosSorter = new Sorter(mob);
}
Expand Down Expand Up @@ -83,6 +76,7 @@ public Sorter(Entity theEntityIn) {
}

//further; more prefered.
@Override
public int compare(BlockPos p_compare_1_, BlockPos p_compare_2_) {
this.pos = AquaticAIFindWaterTarget.this.mob.getPosition();
double d0 = this.pos.distanceSq(p_compare_1_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;

import net.minecraft.entity.ai.goal.Goal.Flag;

public class AquaticAIGetInWater extends Goal {

private final MobEntity creature;
private final double movementSpeed;
private final World world;
Expand All @@ -36,8 +35,11 @@ protected boolean isAttackerInWater() {
return creature.getAttackTarget() != null && !creature.getAttackTarget().isInWater();
}

@Override
public boolean shouldExecute() {
if (creature.isBeingRidden() || creature instanceof TameableEntity && ((TameableEntity) creature).isTamed() || creature.isInWater() || isAttackerInWater() || creature instanceof EntitySiren && (((EntitySiren) creature).isSinging() || ((EntitySiren) creature).wantsToSing())) {
if (creature.isBeingRidden() || creature instanceof TameableEntity && ((TameableEntity) creature).isTamed()
|| creature.isInWater() || isAttackerInWater() || creature instanceof EntitySiren
&& (((EntitySiren) creature).isSinging() || ((EntitySiren) creature).wantsToSing())) {
return false;
} else {
Vector3d Vector3d = this.findPossibleShelter();
Expand All @@ -56,13 +58,15 @@ public boolean shouldExecute() {
/**
* Returns whether an in-progress Goal should continue executing
*/
@Override
public boolean shouldContinueExecuting() {
return !this.creature.getNavigator().noPath();
}

/**
* Execute a one shot task or start executing a continuous task
*/
@Override
public void startExecuting() {
this.creature.getNavigator().tryMoveToXYZ(this.shelterX, this.shelterY, this.shelterZ, this.movementSpeed);
}
Expand All @@ -75,10 +79,12 @@ public Vector3d findPossibleShelter() {
@Nullable
protected Vector3d findPossibleShelter(int xz, int y) {
Random random = this.creature.getRNG();
BlockPos blockpos = new BlockPos(this.creature.getPosX(), this.creature.getBoundingBox().minY, this.creature.getPosZ());
BlockPos blockpos = new BlockPos(this.creature.getPosX(), this.creature.getBoundingBox().minY,
this.creature.getPosZ());

for (int i = 0; i < 10; ++i) {
BlockPos blockpos1 = blockpos.add(random.nextInt(xz * 2) - xz, random.nextInt(y * 2) - y, random.nextInt(xz * 2) - xz);
BlockPos blockpos1 = blockpos.add(random.nextInt(xz * 2) - xz, random.nextInt(y * 2) - y,
random.nextInt(xz * 2) - xz);

if (this.world.getBlockState(blockpos1).getMaterial() == Material.WATER) {
return new Vector3d(blockpos1.getX(), blockpos1.getY(), blockpos1.getZ());
Expand All @@ -87,4 +93,4 @@ protected Vector3d findPossibleShelter(int xz, int y) {

return null;
}
}
}
Loading