From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Fri, 3 Jan 2020 16:24:46 +0100 Subject: [PATCH] Add Mob Goal API diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java new file mode 100644 index 0000000000000000000000000000000000000000..c57c5416c88e2070a082403ab0dda9d7f08d2a57 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/Goal.java @@ -0,0 +1,66 @@ +package com.destroystokyo.paper.entity.ai; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumSet; + +import org.bukkit.entity.Mob; + +/** + * Represents an AI goal of an entity + */ +public interface Goal { + + /** + * Checks if this goal should be activated + * + * @return if this goal should be activated + */ + boolean shouldActivate(); + + /** + * Checks if this goal should stay active, defaults to {@link Goal#shouldActivate()} + * + * @return if this goal should stay active + */ + default boolean shouldStayActive() { + return shouldActivate(); + } + + /** + * Called when this goal gets activated + */ + default void start() { + } + + /** + * Called when this goal gets stopped + */ + default void stop() { + } + + /** + * Called each tick the goal is activated + */ + default void tick() { + } + + /** + * A unique key that identifies this type of goal. Plugins should use their own namespace, not the minecraft + * namespace. Additionally, this key also specifies to what mobs this goal can be applied to + * + * @return the goal key + */ + @NotNull + GoalKey getKey(); + + /** + * Returns a list of all applicable flags for this goal.
+ * + * This method is only called on construction. + * + * @return the subtypes. + */ + @NotNull + EnumSet getTypes(); +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java new file mode 100644 index 0000000000000000000000000000000000000000..9cd98c6fcfa3eb439d9013ef76ef4661175a0e5a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalKey.java @@ -0,0 +1,64 @@ +package com.destroystokyo.paper.entity.ai; + +import com.google.common.base.Objects; + +import org.jetbrains.annotations.NotNull; + +import java.util.StringJoiner; + +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Mob; + +/** + * + * Used to identify a Goal. Consists of a {@link NamespacedKey} and the type of mob the goal can be applied to + * + * @param the type of mob the goal can be applied to + */ +public class GoalKey { + + private final Class entityClass; + private final NamespacedKey namespacedKey; + + private GoalKey(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { + this.entityClass = entityClass; + this.namespacedKey = namespacedKey; + } + + @NotNull + public Class getEntityClass() { + return entityClass; + } + + @NotNull + public NamespacedKey getNamespacedKey() { + return namespacedKey; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GoalKey goalKey = (GoalKey) o; + return Objects.equal(entityClass, goalKey.entityClass) && + Objects.equal(namespacedKey, goalKey.namespacedKey); + } + + @Override + public int hashCode() { + return Objects.hashCode(entityClass, namespacedKey); + } + + @Override + public String toString() { + return new StringJoiner(", ", GoalKey.class.getSimpleName() + "[", "]") + .add("entityClass=" + entityClass) + .add("namespacedKey=" + namespacedKey) + .toString(); + } + + @NotNull + public static GoalKey of(@NotNull Class entityClass, @NotNull NamespacedKey namespacedKey) { + return new GoalKey<>(entityClass, namespacedKey); + } +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java new file mode 100644 index 0000000000000000000000000000000000000000..7024c8f484d2460abf3abfe65a29771d814105ec --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/GoalType.java @@ -0,0 +1,17 @@ +package com.destroystokyo.paper.entity.ai; + +/** + * Represents the subtype of a goal. Used by minecraft to disable certain types of goals if needed. + */ +public enum GoalType { + + MOVE, + LOOK, + JUMP, + TARGET, + /** + * Used to map vanilla goals, that are a behavior goal but don't have a type set... + */ + UNKNOWN_BEHAVIOR, + +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java new file mode 100644 index 0000000000000000000000000000000000000000..e21f7574763dd4f13794f91bbef192ef66a8f5e9 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoals.java @@ -0,0 +1,50 @@ +package com.destroystokyo.paper.entity.ai; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +import org.bukkit.entity.Mob; + +/** + * Represents a part of the "brain" of a mob. It tracks all tasks (running or not), allows adding and removing goals + */ +public interface MobGoals { + + void addGoal(@NotNull T mob, int priority, @NotNull Goal goal); + + void removeGoal(@NotNull T mob, @NotNull Goal goal); + + void removeAllGoals(@NotNull T mob); + + void removeAllGoals(@NotNull T mob, @NotNull GoalType type); + + void removeGoal(@NotNull T mob, @NotNull GoalKey key); + + boolean hasGoal(@NotNull T mob, @NotNull GoalKey key); + + @Nullable + Goal getGoal(@NotNull T mob, @NotNull GoalKey key); + + @NotNull + Collection> getGoals(@NotNull T mob, @NotNull GoalKey key); + + @NotNull + Collection> getAllGoals(@NotNull T mob); + + @NotNull + Collection> getAllGoals(@NotNull T mob, @NotNull GoalType type); + + @NotNull + Collection> getAllGoalsWithout(@NotNull T mob, @NotNull GoalType type); + + @NotNull + Collection> getRunningGoals(@NotNull T mob); + + @NotNull + Collection> getRunningGoals(@NotNull T mob, @NotNull GoalType type); + + @NotNull + Collection> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type); +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index ed65e84868f6b3b9272c8266244d7ab3725a7699..946dc3c3bde31c7a02ac4733ee8c88e63d8baff8 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -2513,6 +2513,16 @@ public final class Bukkit { public static boolean isStopping() { return server.isStopping(); } + + /** + * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager + * + * @return the mob goals manager + */ + @NotNull + public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { + return server.getMobGoals(); + } // Paper end @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java index e87718db19c902fe385328866767e46c397b7e86..000713e09564c96a7d3c9ceb0371de26a11ff82e 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -2188,5 +2188,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @return true if server is in the process of being shutdown */ boolean isStopping(); + + /** + * Returns the {@link com.destroystokyo.paper.entity.ai.MobGoals} manager + * + * @return the mob goals manager + */ + @NotNull + com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); // Paper end }