diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRandomStroll.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRandomStroll.java new file mode 100644 index 00000000..16f5b0cd --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRandomStroll.java @@ -0,0 +1,18 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Move around randomly. + * + * @param speed The speed at which to move around. + * @param interval The amount of ticks to wait (on average) between strolling around. + * @param canDespawn If the entity can despawn. + */ +public record EntityGoalRandomStroll( + double speed, + int interval, + boolean canDespawn +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRandomSwimming.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRandomSwimming.java new file mode 100644 index 00000000..400644d4 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRandomSwimming.java @@ -0,0 +1,16 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Swim around randomly. + * + * @param speed The speed at which to move around. + * @param interval The amount of ticks to wait (on average) between strolling around. + */ +public record EntityGoalRandomSwimming( + double speed, + int interval +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedAttack.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedAttack.java new file mode 100644 index 00000000..db20c95f --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedAttack.java @@ -0,0 +1,22 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Ranged attack. + *

+ * Only supports mobs that have ranged attacks. + * + * @param mobSpeed The mob speed. + * @param minInterval The minimum interval between attacks (in ticks). + * @param maxInterval The maximum interval between attacks (in ticks). + * @param maxRange The max range at which to attack. + */ +public record EntityGoalRangedAttack( + double mobSpeed, + int minInterval, + int maxInterval, + double maxRange +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedBowAttack.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedBowAttack.java new file mode 100644 index 00000000..5f6f1a84 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedBowAttack.java @@ -0,0 +1,20 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Ranged attack. + *

+ * Only supports monsters that have bow attacks. + * + * @param speed The speed. + * @param attackInterval The interval between attacks (in ticks). + * @param range The max range at which to attack. + */ +public record EntityGoalRangedBowAttack( + double speed, + int attackInterval, + double range +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedCrossbowAttack.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedCrossbowAttack.java new file mode 100644 index 00000000..143f4d79 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalRangedCrossbowAttack.java @@ -0,0 +1,18 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Ranged attack. + *

+ * Only supports monsters that have crossbow attacks. + * + * @param speed The speed. + * @param range The max range at which to attack. + */ +public record EntityGoalRangedCrossbowAttack( + double speed, + double range +) implements EntityGoal { + +} diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EcoControlledEntity.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EcoControlledEntity.kt index ee4d51cb..4b87ea11 100644 --- a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EcoControlledEntity.kt +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EcoControlledEntity.kt @@ -13,7 +13,10 @@ class EcoControlledEntity( val craft = handle as? CraftEntity ?: return this val nms = craft.handle as? net.minecraft.world.entity.PathfinderMob ?: return this - nms.goalSelector.addGoal(priority, goal.getImplementation().generateNMSGoal(goal, nms)) + nms.goalSelector.addGoal( + priority, + goal.getImplementation().generateNMSGoal(goal, nms) ?: return this + ) return this } @@ -22,7 +25,9 @@ class EcoControlledEntity( val craft = handle as? CraftEntity ?: return this val nms = craft.handle as? net.minecraft.world.entity.PathfinderMob ?: return this - nms.targetSelector.addGoal(priority, goal.getImplementation().generateNMSGoal(goal, nms)) + nms.targetSelector.addGoal( + priority, goal.getImplementation().generateNMSGoal(goal, nms) ?: return this + ) return this } diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityGoals.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityGoals.kt index d1c76482..f0692c7a 100644 --- a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityGoals.kt +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityGoals.kt @@ -21,6 +21,11 @@ import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalOcelotAttack import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalOpenDoors import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalPanic import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalRandomLookAround +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalRandomStroll +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalRandomSwimming +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalRangedAttack +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalRangedBowAttack +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalRangedCrossbowAttack import net.minecraft.world.entity.PathfinderMob import net.minecraft.world.entity.ai.goal.AvoidEntityGoal import net.minecraft.world.entity.ai.goal.BreakDoorGoal @@ -43,6 +48,12 @@ import net.minecraft.world.entity.ai.goal.OcelotAttackGoal import net.minecraft.world.entity.ai.goal.OpenDoorGoal import net.minecraft.world.entity.ai.goal.PanicGoal import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal +import net.minecraft.world.entity.ai.goal.RandomStrollGoal +import net.minecraft.world.entity.ai.goal.RandomSwimmingGoal +import net.minecraft.world.entity.ai.goal.RangedAttackGoal +import net.minecraft.world.entity.ai.goal.RangedBowAttackGoal +import net.minecraft.world.entity.ai.goal.RangedCrossbowAttackGoal +import net.minecraft.world.entity.monster.RangedAttackMob import net.minecraft.world.entity.player.Player fun T.getImplementation(): EcoEntityGoal { @@ -68,12 +79,17 @@ fun T.getImplementation(): EcoEntityGoal { is EntityGoalOpenDoors -> OpenDoorsImpl is EntityGoalPanic -> PanicImpl is EntityGoalRandomLookAround -> RandomLookAroundImpl + is EntityGoalRandomStroll -> RandomStrollImpl + is EntityGoalRandomSwimming -> RandomSwimmingImpl + is EntityGoalRangedAttack -> RangedAttackImpl + is EntityGoalRangedBowAttack -> RangedBowAttackImpl + is EntityGoalRangedCrossbowAttack -> RangedCrossbowAttackImpl else -> throw IllegalArgumentException("Unknown API goal!") } as EcoEntityGoal } interface EcoEntityGoal { - fun generateNMSGoal(apiGoal: T, entity: PathfinderMob): Goal + fun generateNMSGoal(apiGoal: T, entity: PathfinderMob): Goal? } object AvoidEntityImpl : EcoEntityGoal { @@ -264,3 +280,58 @@ object RandomLookAroundImpl : EcoEntityGoal { ) } } + +object RandomStrollImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalRandomStroll, entity: PathfinderMob): Goal { + return RandomStrollGoal( + entity, + apiGoal.speed, + apiGoal.interval, + apiGoal.canDespawn + ) + } +} + +object RandomSwimmingImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalRandomSwimming, entity: PathfinderMob): Goal { + return RandomSwimmingGoal( + entity, + apiGoal.speed, + apiGoal.interval + ) + } +} + +object RangedAttackImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalRangedAttack, entity: PathfinderMob): Goal? { + return RangedAttackGoal( + entity as? RangedAttackMob ?: return null, + apiGoal.mobSpeed, + apiGoal.minInterval, + apiGoal.maxInterval, + apiGoal.maxRange.toFloat() + ) + } +} + +object RangedBowAttackImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalRangedBowAttack, entity: PathfinderMob): Goal? { + return RangedBowAttackGoal( + entity.tryCast() ?: return null, + apiGoal.speed, + apiGoal.attackInterval, + apiGoal.range.toFloat() + ) + } +} + +object RangedCrossbowAttackImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalRangedCrossbowAttack, entity: PathfinderMob): Goal? { + return RangedCrossbowAttackGoal( + entity.tryCast() ?: return null, + apiGoal.speed, + apiGoal.range.toFloat() + ) + } +} + diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityUtils.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityUtils.kt index b60ab49d..4d6a3001 100644 --- a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityUtils.kt +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityUtils.kt @@ -4,6 +4,7 @@ import com.github.benmanes.caffeine.cache.Caffeine import com.github.benmanes.caffeine.cache.LoadingCache import net.minecraft.world.entity.AgeableMob import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.entity.PathfinderMob import net.minecraft.world.entity.TamableAnimal import net.minecraft.world.entity.ambient.AmbientCreature import net.minecraft.world.entity.animal.Animal @@ -74,3 +75,8 @@ fun Class.toNMSClass(): Class PathfinderMob.tryCast(): T? { + @Suppress("UNCHECKED_CAST") + return this as? T +} diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/TargetGoals.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/TargetGoals.kt index e38b18d3..eb567ef8 100644 --- a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/TargetGoals.kt +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/TargetGoals.kt @@ -18,7 +18,7 @@ fun T.getImplementation(): EcoTargetGoal { } interface EcoTargetGoal { - fun generateNMSGoal(apiGoal: T, entity: PathfinderMob): Goal + fun generateNMSGoal(apiGoal: T, entity: PathfinderMob): Goal? } object HurtByImpl : EcoTargetGoal {