diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/CustomGoal.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/CustomGoal.java
index 420b2601..b374ba5f 100644
--- a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/CustomGoal.java
+++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/CustomGoal.java
@@ -3,6 +3,10 @@ package com.willfp.eco.core.entities.ai;
import org.bukkit.entity.Mob;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Set;
+
/**
* Base interface for all custom goals.
*
@@ -10,7 +14,12 @@ import org.jetbrains.annotations.NotNull;
*
* @param The type of mob that this goal can be applied to.
*/
-public interface CustomGoal extends EntityGoal, TargetGoal {
+public abstract class CustomGoal implements EntityGoal, TargetGoal {
+ /**
+ * The flags for the goal.
+ */
+ private final Set flags = EnumSet.noneOf(GoalFlag.class);
+
/**
* Initialize the goal with a mob.
*
@@ -18,7 +27,7 @@ public interface CustomGoal extends EntityGoal, TargetGoal
*
* @param mob The mob.
*/
- void initialize(@NotNull T mob);
+ public abstract void initialize(@NotNull T mob);
/**
* Get if the goal can be used.
@@ -26,7 +35,7 @@ public interface CustomGoal extends EntityGoal, TargetGoal
*
* @return If the goal can be used.
*/
- boolean canUse();
+ public abstract boolean canUse();
/**
* Tick the goal.
@@ -35,7 +44,7 @@ public interface CustomGoal extends EntityGoal, TargetGoal
*
* Runs after {@link this#start()}.
*/
- default void tick() {
+ public void tick() {
// Override when needed.
}
@@ -44,7 +53,7 @@ public interface CustomGoal extends EntityGoal, TargetGoal
*
* Runs once {@link this#canUse()} returns true.
*/
- default void start() {
+ public void start() {
// Override when needed.
}
@@ -53,12 +62,50 @@ public interface CustomGoal extends EntityGoal, TargetGoal
*
* Runs once {@link this#canUse()} returns false.
*/
- default void stop() {
+ public void stop() {
// Override when needed.
}
+ /**
+ * Get if the goal can continue to be used.
+ *
+ * @return If the goal can continue to be used.
+ */
+ public boolean canContinueToUse() {
+ return this.canUse();
+ }
+
+ /**
+ * Get if the goal is interruptable.
+ *
+ * @return If interruptable.
+ */
+ public boolean isInterruptable() {
+ return true;
+ }
+
+ /**
+ * Get the goal flags.
+ *
+ * @return The flags.
+ */
+ public EnumSet getFlags() {
+ return EnumSet.copyOf(this.flags);
+ }
+
+ /**
+ * Set the flags for the goal.
+ *
+ * @param flags The flags.
+ */
+ public void setFlags(@NotNull final Collection flags) {
+ this.flags.clear();
+ this.flags.addAll(flags);
+ }
+
@Override
- default T addToEntity(@NotNull T entity, int priority) {
+ public T addToEntity(@NotNull final T entity,
+ final int priority) {
throw new UnsupportedOperationException(
"Shorthand syntax is not supported for custom goals by default as they can be both entity and target goals."
);
diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/GoalFlag.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/GoalFlag.java
new file mode 100644
index 00000000..d8d863f9
--- /dev/null
+++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/GoalFlag.java
@@ -0,0 +1,26 @@
+package com.willfp.eco.core.entities.ai;
+
+/**
+ * Flags for ai goals.
+ */
+public enum GoalFlag {
+ /**
+ * Move.
+ */
+ MOVE,
+
+ /**
+ * Look around.
+ */
+ LOOK,
+
+ /**
+ * Jump.
+ */
+ JUMP,
+
+ /**
+ * Target.
+ */
+ TARGET
+}
diff --git a/eco-core/core-nms/nms-common/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/common/ai/CustomGoals.kt b/eco-core/core-nms/nms-common/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/common/ai/CustomGoals.kt
index 739efd04..4ef59e98 100644
--- a/eco-core/core-nms/nms-common/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/common/ai/CustomGoals.kt
+++ b/eco-core/core-nms/nms-common/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/common/ai/CustomGoals.kt
@@ -1,8 +1,10 @@
package com.willfp.eco.internal.spigot.proxy.common.ai
import com.willfp.eco.core.entities.ai.CustomGoal
+import com.willfp.eco.core.entities.ai.GoalFlag
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.entity.ai.goal.Goal
+import java.util.EnumSet
object CustomGoalFactory : EntityGoalFactory>, TargetGoalFactory> {
override fun create(apiGoal: CustomGoal<*>, entity: PathfinderMob): Goal {
@@ -10,6 +12,30 @@ object CustomGoalFactory : EntityGoalFactory>, TargetGoalFactory.toEcoFlags(): Collection {
+ return this.mapNotNull {
+ when (it) {
+ Goal.Flag.JUMP -> GoalFlag.JUMP
+ Goal.Flag.LOOK -> GoalFlag.LOOK
+ Goal.Flag.MOVE -> GoalFlag.MOVE
+ Goal.Flag.TARGET -> GoalFlag.TARGET
+ else -> null
+ }
+ }
+}
+
+private fun Collection.toNMSFlags(): Collection {
+ return this.mapNotNull {
+ when (it) {
+ GoalFlag.JUMP -> Goal.Flag.JUMP
+ GoalFlag.LOOK -> Goal.Flag.LOOK
+ GoalFlag.MOVE -> Goal.Flag.MOVE
+ GoalFlag.TARGET -> Goal.Flag.TARGET
+ else -> null
+ }
+ }
+}
+
private class NMSCustomGoal(
private val customEntityGoal: CustomGoal,
entity: PathfinderMob
@@ -17,6 +43,7 @@ private class NMSCustomGoal(
init {
@Suppress("UNCHECKED_CAST")
customEntityGoal.initialize(entity.bukkitMob as T)
+ this.setFlags(EnumSet.copyOf(customEntityGoal.flags.toNMSFlags()))
}
override fun canUse(): Boolean {
@@ -34,4 +61,17 @@ private class NMSCustomGoal(
override fun stop() {
customEntityGoal.stop()
}
+
+ override fun canContinueToUse(): Boolean {
+ return customEntityGoal.canContinueToUse()
+ }
+
+ override fun isInterruptable(): Boolean {
+ return customEntityGoal.isInterruptable
+ }
+
+ override fun setFlags(controls: EnumSet) {
+ super.setFlags(controls)
+ customEntityGoal.setFlags(controls.toEcoFlags())
+ }
}