diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/ControlledEntity.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/ControlledEntity.java index 7cae6f6d..5a5bc926 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/ControlledEntity.java +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/ControlledEntity.java @@ -2,6 +2,7 @@ package com.willfp.eco.core.entities.ai; import com.willfp.eco.core.Eco; import com.willfp.eco.core.entities.ai.goals.EntityGoal; +import com.willfp.eco.core.entities.ai.goals.TargetGoal; import org.bukkit.entity.Mob; import org.jetbrains.annotations.NotNull; @@ -16,8 +17,8 @@ public interface ControlledEntity { * @param goal The goal. * @return The entity. */ - ControlledEntity addTarget(int priority, - @NotNull EntityGoal goal); + ControlledEntity addTargetGoal(int priority, + @NotNull TargetGoal goal); /** * Add a goal to the entity. @@ -26,8 +27,8 @@ public interface ControlledEntity { * @param goal The goal. * @return The entity. */ - ControlledEntity addGoal(int priority, - @NotNull EntityGoal goal); + ControlledEntity addEntityGoal(int priority, + @NotNull EntityGoal goal); /** * Get the mob back from the controlled entity. diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/EntityGoalNearestAttackableTarget.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/EntityGoalNearestAttackableTarget.java deleted file mode 100644 index 49e0ec3e..00000000 --- a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/EntityGoalNearestAttackableTarget.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.willfp.eco.core.entities.ai.goals; - -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; - -public record EntityGoalNearestAttackableTarget( - @NotNull Class targetClass, - boolean checkVisibility -) implements EntityGoal { - -} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/TargetGoal.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/TargetGoal.java new file mode 100644 index 00000000..88f91bf0 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/TargetGoal.java @@ -0,0 +1,8 @@ +package com.willfp.eco.core.entities.ai.goals; + +/** + * A goal for entity AI. + */ +public interface TargetGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalAvoidEntity.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalAvoidEntity.java new file mode 100644 index 00000000..098d1508 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalAvoidEntity.java @@ -0,0 +1,26 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +/** + * Avoid entities. + * + * @param avoidClass The entity classes to avoid. + * @param fleeDistance The distance to flee to. + * @param slowSpeed The slow movement speed. + * @param fastSpeed The fast movement speed. + * @param filter The filter for entities to check if they should be avoided. + */ +public record EntityGoalAvoidEntity( + @NotNull Class avoidClass, + double fleeDistance, + double slowSpeed, + double fastSpeed, + @NotNull Predicate filter +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalBreakDoor.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalBreakDoor.java new file mode 100644 index 00000000..cc4cdb82 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalBreakDoor.java @@ -0,0 +1,14 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Break doors. + * + * @param maxProgress The time taken to break the door (any integer above 240). + */ +public record EntityGoalBreakDoor( + int maxProgress +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalBreatheAir.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalBreatheAir.java new file mode 100644 index 00000000..9c4898ba --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalBreatheAir.java @@ -0,0 +1,11 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Breathe air. + */ +public record EntityGoalBreatheAir( +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalEatBlock.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalEatBlock.java new file mode 100644 index 00000000..06969396 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalEatBlock.java @@ -0,0 +1,11 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Eat block. + */ +public record EntityGoalEatBlock( +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFleeSun.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFleeSun.java new file mode 100644 index 00000000..22768836 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFleeSun.java @@ -0,0 +1,14 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Flee sun. + * + * @param speed The speed at which to flee. + */ +public record EntityGoalFleeSun( + double speed +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFloat.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFloat.java new file mode 100644 index 00000000..66a1ad47 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFloat.java @@ -0,0 +1,11 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Float in water. + */ +public record EntityGoalFloat( +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFollowBoats.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFollowBoats.java new file mode 100644 index 00000000..c441538e --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFollowBoats.java @@ -0,0 +1,11 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Follow boats. + */ +public record EntityGoalFollowBoats( +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFollowMobs.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFollowMobs.java new file mode 100644 index 00000000..43565c14 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalFollowMobs.java @@ -0,0 +1,18 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; + +/** + * Follow other mobs. + * + * @param speed The speed at which to follow. + * @param minDistance The minimum follow distance. + * @param maxDistance The maximum follow distance. + */ +public record EntityGoalFollowMobs( + double speed, + double minDistance, + double maxDistance +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalInteract.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalInteract.java new file mode 100644 index 00000000..2da8cd1f --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/entity/EntityGoalInteract.java @@ -0,0 +1,20 @@ +package com.willfp.eco.core.entities.ai.goals.entity; + +import com.willfp.eco.core.entities.ai.goals.EntityGoal; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; + +/** + * Interact with other mobs. + * + * @param targetClass The type of entity to interact with. + * @param range The range at which to interact. + * @param chance The chance for interaction, as a percentage. + */ +public record EntityGoalInteract( + @NotNull Class targetClass, + double range, + double chance +) implements EntityGoal { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/target/TargetGoalHurtBy.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/target/TargetGoalHurtBy.java new file mode 100644 index 00000000..39970cb5 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/target/TargetGoalHurtBy.java @@ -0,0 +1,23 @@ +package com.willfp.eco.core.entities.ai.goals.target; + +import com.willfp.eco.core.entities.ai.goals.TargetGoal; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; + +/** + * Hurt by entity. + * + * @param blacklist The entities not to attack when hurt by. + */ +public record TargetGoalHurtBy( + @NotNull Class... blacklist +) implements TargetGoal { + /** + * Create target goal. + * + * @param blacklist The entities not to attack when hurt by. + */ + @SafeVarargs + public TargetGoalHurtBy { + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/target/TargetGoalNearestAttackable.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/target/TargetGoalNearestAttackable.java new file mode 100644 index 00000000..a36baa51 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/goals/target/TargetGoalNearestAttackable.java @@ -0,0 +1,18 @@ +package com.willfp.eco.core.entities.ai.goals.target; + +import com.willfp.eco.core.entities.ai.goals.TargetGoal; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; + +/** + * Target nearest attackable entity. + * + * @param targetClass The types of entities to attack. + * @param checkVisibility If visibility should be checked. + */ +public record TargetGoalNearestAttackable( + @NotNull Class targetClass, + boolean checkVisibility +) implements TargetGoal { + +} 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 51c48483..ee4d51cb 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 @@ -2,26 +2,27 @@ package com.willfp.eco.internal.spigot.proxy.v1_17_R1.ai import com.willfp.eco.core.entities.ai.ControlledEntity import com.willfp.eco.core.entities.ai.goals.EntityGoal +import com.willfp.eco.core.entities.ai.goals.TargetGoal import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity import org.bukkit.entity.Mob class EcoControlledEntity( private val handle: Mob ) : ControlledEntity { - override fun addGoal(priority: Int, goal: EntityGoal): ControlledEntity { + override fun addEntityGoal(priority: Int, goal: EntityGoal): ControlledEntity { val craft = handle as? CraftEntity ?: return this - val nms = craft.handle as? net.minecraft.world.entity.Mob ?: return this + val nms = craft.handle as? net.minecraft.world.entity.PathfinderMob ?: return this - nms.goalSelector.addGoal(priority, GoalFactory.getImplementation(goal).generateNMSGoal(goal, nms)) + nms.goalSelector.addGoal(priority, goal.getImplementation().generateNMSGoal(goal, nms)) return this } - override fun addTarget(priority: Int, goal: EntityGoal): ControlledEntity { + override fun addTargetGoal(priority: Int, goal: TargetGoal): ControlledEntity { val craft = handle as? CraftEntity ?: return this - val nms = craft.handle as? net.minecraft.world.entity.Mob ?: return this + val nms = craft.handle as? net.minecraft.world.entity.PathfinderMob ?: return this - nms.targetSelector.addGoal(priority, GoalFactory.getImplementation(goal).generateNMSGoal(goal, nms)) + nms.targetSelector.addGoal(priority, goal.getImplementation().generateNMSGoal(goal, nms)) 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 1456c7f2..2e73ab55 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 @@ -1,17 +1,127 @@ package com.willfp.eco.internal.spigot.proxy.v1_17_R1.ai import com.willfp.eco.core.entities.ai.goals.EntityGoal -import com.willfp.eco.core.entities.ai.goals.EntityGoalNearestAttackableTarget -import net.minecraft.world.entity.Mob +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalAvoidEntity +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalBreakDoor +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalBreatheAir +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalEatBlock +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalFleeSun +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalFloat +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalFollowBoats +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalFollowMobs +import com.willfp.eco.core.entities.ai.goals.entity.EntityGoalInteract +import net.minecraft.world.entity.PathfinderMob +import net.minecraft.world.entity.ai.goal.AvoidEntityGoal +import net.minecraft.world.entity.ai.goal.BreakDoorGoal +import net.minecraft.world.entity.ai.goal.BreathAirGoal +import net.minecraft.world.entity.ai.goal.EatBlockGoal +import net.minecraft.world.entity.ai.goal.FleeSunGoal +import net.minecraft.world.entity.ai.goal.FloatGoal +import net.minecraft.world.entity.ai.goal.FollowBoatGoal +import net.minecraft.world.entity.ai.goal.FollowMobGoal import net.minecraft.world.entity.ai.goal.Goal -import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal +import net.minecraft.world.entity.ai.goal.InteractGoal + +fun T.getImplementation(): EcoEntityGoal { + @Suppress("UNCHECKED_CAST") + return when (this) { + is EntityGoalAvoidEntity -> AvoidEntityImpl + is EntityGoalBreakDoor -> BreakDoorImpl + is EntityGoalBreatheAir -> BreatheAirImpl + is EntityGoalEatBlock -> EatBlockImpl + is EntityGoalFleeSun -> FleeSunImpl + is EntityGoalFloat -> FloatImpl + is EntityGoalFollowBoats -> FollowBoatsImpl + is EntityGoalFollowMobs -> FollowMobsImpl + is EntityGoalInteract -> InteractImpl + else -> throw IllegalArgumentException("Unknown API goal!") + } as EcoEntityGoal +} interface EcoEntityGoal { - fun generateNMSGoal(apiGoal: T, entity: Mob): Goal + fun generateNMSGoal(apiGoal: T, entity: PathfinderMob): Goal } -class NearestAttackableTargetImpl : EcoEntityGoal { - override fun generateNMSGoal(apiGoal: EntityGoalNearestAttackableTarget, entity: Mob): Goal { - return NearestAttackableTargetGoal(entity, apiGoal.targetClass, apiGoal.checkVisibility) +object AvoidEntityImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalAvoidEntity, entity: PathfinderMob): Goal { + return AvoidEntityGoal( + entity, + apiGoal.avoidClass.toNMSClass(), + apiGoal.fleeDistance.toFloat(), + apiGoal.slowSpeed, + apiGoal.fastSpeed + ) { apiGoal.filter.test(it.toBukkitEntity()) } + } +} + +object BreakDoorImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalBreakDoor, entity: PathfinderMob): Goal { + return BreakDoorGoal( + entity, + apiGoal.maxProgress + ) { true } + } +} + +object BreatheAirImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalBreatheAir, entity: PathfinderMob): Goal { + return BreathAirGoal( + entity + ) + } +} + +object EatBlockImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalEatBlock, entity: PathfinderMob): Goal { + return EatBlockGoal( + entity + ) + } +} + +object FleeSunImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalFleeSun, entity: PathfinderMob): Goal { + return FleeSunGoal( + entity, + apiGoal.speed + ) + } +} + +object FloatImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalFloat, entity: PathfinderMob): Goal { + return FloatGoal( + entity + ) + } +} + +object FollowBoatsImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalFollowBoats, entity: PathfinderMob): Goal { + return FollowBoatGoal( + entity + ) + } +} + +object FollowMobsImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalFollowMobs, entity: PathfinderMob): Goal { + return FollowMobGoal( + entity, + apiGoal.speed, + apiGoal.minDistance.toFloat(), + apiGoal.maxDistance.toFloat(), + ) + } +} + +object InteractImpl : EcoEntityGoal { + override fun generateNMSGoal(apiGoal: EntityGoalInteract, entity: PathfinderMob): Goal { + return InteractGoal( + entity, + apiGoal.targetClass.toNMSClass(), + apiGoal.range.toFloat(), + apiGoal.chance.toFloat() / 100f, + ) } } 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 new file mode 100644 index 00000000..b60ab49d --- /dev/null +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/EntityUtils.kt @@ -0,0 +1,76 @@ +package com.willfp.eco.internal.spigot.proxy.v1_17_R1.ai + +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.TamableAnimal +import net.minecraft.world.entity.ambient.AmbientCreature +import net.minecraft.world.entity.animal.Animal +import net.minecraft.world.entity.monster.AbstractIllager +import net.minecraft.world.entity.monster.SpellcasterIllager +import net.minecraft.world.entity.monster.piglin.AbstractPiglin +import net.minecraft.world.entity.player.Player +import org.bukkit.Bukkit +import org.bukkit.Location +import org.bukkit.craftbukkit.v1_17_R1.CraftServer +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity +import org.bukkit.entity.AbstractHorse +import org.bukkit.entity.AbstractSkeleton +import org.bukkit.entity.AbstractVillager +import org.bukkit.entity.Ageable +import org.bukkit.entity.Ambient +import org.bukkit.entity.Animals +import org.bukkit.entity.HumanEntity +import org.bukkit.entity.Illager +import org.bukkit.entity.Mob +import org.bukkit.entity.Monster +import org.bukkit.entity.PiglinAbstract +import org.bukkit.entity.Spellcaster +import org.bukkit.entity.Tameable +import java.util.Optional + +private val mappedClasses = mapOf( + Pair(AbstractHorse::class.java, net.minecraft.world.entity.animal.horse.AbstractHorse::class.java), + Pair(AbstractSkeleton::class.java, net.minecraft.world.entity.monster.AbstractSkeleton::class.java), + Pair(AbstractVillager::class.java, net.minecraft.world.entity.npc.AbstractVillager::class.java), + Pair(Ageable::class.java, AgeableMob::class.java), + Pair(Ambient::class.java, AmbientCreature::class.java), + Pair(Animals::class.java, Animal::class.java), + Pair(HumanEntity::class.java, Player::class.java), // Can't spawn players + Pair(Illager::class.java, AbstractIllager::class.java), + Pair(Mob::class.java, net.minecraft.world.entity.Mob::class.java), + Pair(Monster::class.java, net.minecraft.world.entity.monster.Monster::class.java), + Pair(PiglinAbstract::class.java, AbstractPiglin::class.java), + Pair(org.bukkit.entity.Player::class.java, Player::class.java), // Can't spawn players + Pair(Spellcaster::class.java, SpellcasterIllager::class.java), + Pair(Tameable::class.java, TamableAnimal::class.java) +) + +private val cache: LoadingCache, Optional>> = + Caffeine.newBuilder() + .build { + val mapped = mappedClasses[it] + if (mapped != null) { + return@build Optional.of(mapped) + } + + val world = Bukkit.getWorlds().first() as CraftWorld + + @Suppress("UNCHECKED_CAST") + val nmsClass = Optional.ofNullable(runCatching { + world.createEntity( + Location(world, 0.0, 100.0, 0.0), + it + )::class.java as Class + }.getOrNull()) + + return@build nmsClass + } + +fun Class.toNMSClass(): Class = + cache.get(this).orElseThrow { IllegalArgumentException("Invalid/Unsupported entity type!") } + +fun LivingEntity.toBukkitEntity(): org.bukkit.entity.LivingEntity? = + CraftEntity.getEntity(Bukkit.getServer() as CraftServer, this) as? org.bukkit.entity.LivingEntity diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/GoalFactory.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/GoalFactory.kt deleted file mode 100644 index 04b63264..00000000 --- a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/GoalFactory.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.willfp.eco.internal.spigot.proxy.v1_17_R1.ai - -import com.willfp.eco.core.entities.ai.goals.EntityGoal -import com.willfp.eco.core.entities.ai.goals.EntityGoalNearestAttackableTarget - -object GoalFactory { - fun getImplementation(apiGoal: T): EcoEntityGoal { - @Suppress("UNCHECKED_CAST") - return when (apiGoal) { - is EntityGoalNearestAttackableTarget -> NearestAttackableTargetImpl() - else -> throw IllegalArgumentException("Unknown API goal!") - } as EcoEntityGoal - } -} 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 new file mode 100644 index 00000000..e38b18d3 --- /dev/null +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/ai/TargetGoals.kt @@ -0,0 +1,41 @@ +package com.willfp.eco.internal.spigot.proxy.v1_17_R1.ai + +import com.willfp.eco.core.entities.ai.goals.TargetGoal +import com.willfp.eco.core.entities.ai.goals.target.TargetGoalHurtBy +import com.willfp.eco.core.entities.ai.goals.target.TargetGoalNearestAttackable +import net.minecraft.world.entity.PathfinderMob +import net.minecraft.world.entity.ai.goal.Goal +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal + +fun T.getImplementation(): EcoTargetGoal { + @Suppress("UNCHECKED_CAST") + return when (this) { + is TargetGoalHurtBy -> HurtByImpl + is TargetGoalNearestAttackable -> NearestAttackableImpl + else -> throw IllegalArgumentException("Unknown API goal!") + } as EcoTargetGoal +} + +interface EcoTargetGoal { + fun generateNMSGoal(apiGoal: T, entity: PathfinderMob): Goal +} + +object HurtByImpl : EcoTargetGoal { + override fun generateNMSGoal(apiGoal: TargetGoalHurtBy, entity: PathfinderMob): Goal { + return HurtByTargetGoal( + entity, + *apiGoal.blacklist.map { it.toNMSClass() }.toTypedArray() + ) + } +} + +object NearestAttackableImpl : EcoTargetGoal { + override fun generateNMSGoal(apiGoal: TargetGoalNearestAttackable, entity: PathfinderMob): Goal { + return NearestAttackableTargetGoal( + entity, + apiGoal.targetClass.toNMSClass(), + apiGoal.checkVisibility + ) + } +}