Paper/patches/api/0474-Add-preliminary-API-fo...

203 lines
8.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Janet Blackquill <uhhadd@gmail.com>
Date: Fri, 26 Apr 2024 23:45:11 -0400
Subject: [PATCH] Add preliminary API for working with 'new' mob AI system
diff --git a/src/main/java/io/papermc/paper/entity/ai/Activity.java b/src/main/java/io/papermc/paper/entity/ai/Activity.java
new file mode 100644
index 0000000000000000000000000000000000000000..0dff7ba2e36c1185453832e28466c82ccb2cd621
--- /dev/null
+++ b/src/main/java/io/papermc/paper/entity/ai/Activity.java
@@ -0,0 +1,9 @@
+package io.papermc.paper.entity.ai;
+
+import org.bukkit.Keyed;
+
+/**
+ * An Activity is a key to a list of tasks in a Brain.
+ */
+public interface Activity extends Keyed {
+}
diff --git a/src/main/java/io/papermc/paper/entity/ai/Brain.java b/src/main/java/io/papermc/paper/entity/ai/Brain.java
new file mode 100644
index 0000000000000000000000000000000000000000..b359ece13fece6d89b1a1cbf55a78af8152a93de
--- /dev/null
+++ b/src/main/java/io/papermc/paper/entity/ai/Brain.java
@@ -0,0 +1,49 @@
+package io.papermc.paper.entity.ai;
+
+import java.util.List;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Entity;
+import org.bukkit.Location;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A brain is the central AI for some modern Minecraft entities such as
+ * villagers and sniffers.
+ */
+public interface Brain<E extends LivingEntity> {
+ /**
+ * If the tasks in the given `activity` can be run, the brain will switch to
+ * the given `activity`.
+ */
+ public void useActivityIfPossible(@NotNull Activity activity);
+ /**
+ * Makes the brain switch to the default activity.
+ */
+ public void useDefaultActivity();
+ /**
+ * Sets the tasks for the given `activity` to the provided list of `tasks`.
+ */
+ ////// TODO: what is that int parameter doing
+ public void setTasksForActivity(@NotNull Activity activity, int begin, @NotNull List<Task<E>> tasks);
+ /**
+ * Clears all tasks for activities associated with this brain.
+ */
+ public void clearActivities();
+ /**
+ * Sets the default activity for this brain.
+ */
+ public void setDefaultActivity(@NotNull Activity activity);
+ /**
+ * Checks whether the given activity is active.
+ */
+ public boolean isActive(@NotNull Activity activity);
+ /**
+ * Sets the entity's current walk target to the given location.
+ */
+ public void setWalkTarget(@NotNull Location location, float speed, int completeWithinDistance);
+ /**
+ * Sets the entity's current walk target to the given entity.
+ */
+ public void setWalkTarget(@NotNull Entity entity, float speed, int completeWithinDistance);
+}
+
diff --git a/src/main/java/io/papermc/paper/entity/ai/Task.java b/src/main/java/io/papermc/paper/entity/ai/Task.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ee58cbb3a520a473e28e48e378c8a9fcb7d24eb
--- /dev/null
+++ b/src/main/java/io/papermc/paper/entity/ai/Task.java
@@ -0,0 +1,10 @@
+package io.papermc.paper.entity.ai;
+
+import org.bukkit.entity.LivingEntity;
+
+/**
+ * A task can be associated with an Activity in a Brain in order
+ * to instruct the entity to do something.
+ */
+public interface Task<E extends LivingEntity> {
+}
\ No newline at end of file
diff --git a/src/main/java/io/papermc/paper/entity/ai/Tasks.java b/src/main/java/io/papermc/paper/entity/ai/Tasks.java
new file mode 100644
index 0000000000000000000000000000000000000000..955dec447a3b93016b62b161b5018fd75251f962
--- /dev/null
+++ b/src/main/java/io/papermc/paper/entity/ai/Tasks.java
@@ -0,0 +1,45 @@
+package io.papermc.paper.entity.ai;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Mob;
+import org.bukkit.entity.memory.MemoryKey;
+import org.jetbrains.annotations.NotNull;
+import java.util.function.Predicate;
+import java.util.function.Function;
+import org.bukkit.entity.LivingEntity;
+import java.util.Map;
+
+public interface Tasks {
+ /**
+ * Instructs the entity to get within N blocks of the block location.
+ */
+ public <Entity extends Mob> @NotNull Task<Entity> walkToWalkTarget(int minRunTime, int maxRunTime);
+ /**
+ * Instructs the entity to swim if it is in water.
+ */
+ public <Entity extends Mob> @NotNull Task<Entity> swimIfInWater(float chance);
+ /**
+ * Instructs the entity to panic if it is hit, freezing, or on fire.
+ */
+ public <Entity extends Mob> @NotNull Task<Entity> panicOnDamage(float speed);
+ /**
+ * Instructs the entity to change its look target to the closest target
+ * for which the predicate returns true.
+ */
+ public <Entity extends LivingEntity> @NotNull Task<Entity> setLookTarget(@NotNull Predicate<LivingEntity> predicate, float maximumDistance);
+ /**
+ * Instructs the entity to set its walk target to the look target if it matches the given predicate.
+ *
+ * @param speed a function defining the speed at which the entity will walk to the given target
+ * @param completionRange the distance in blocks that the entity will attempt to get within
+ */
+ public <Entity extends LivingEntity> @NotNull Task<Entity> setWalkTargetToLookTarget(@NotNull Predicate<LivingEntity> predicate, @NotNull Function<LivingEntity, Float> speed, int completionRange);
+ /**
+ * Instructs the entity to look at the look target.
+ */
+ public <Entity extends Mob> @NotNull Task<Entity> lookAtLookTarget(int minRunTime, int maxRunTime);
+ /**
+ * Instructs the entity to run one of the given tasks with weighted probability.
+ */
+ public <Entity extends LivingEntity> @NotNull Task<Entity> runOneOf(@NotNull Map<Task<? super Entity>, Integer> tasks);
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java
index c4b30b16ce4db754b958c493ad86d0863592c263..05f96057ffdd488877517625ce82dc83712150c5 100644
--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
@@ -8,6 +8,7 @@ import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.bukkit.inventory.meta.trim.TrimPattern;
import org.jetbrains.annotations.ApiStatus;
+import io.papermc.paper.entity.ai.Activity;
import static io.papermc.paper.registry.RegistryKeyImpl.create;
@@ -35,6 +36,11 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
* @see io.papermc.paper.registry.keys.GameEventKeys
*/
RegistryKey<GameEvent> GAME_EVENT = create("game_event");
+ /**
+ * Built-in registry for activities
+ * @see io.papermc.paper.registry.keys.ActivityKeys
+ */
+ RegistryKey<Activity> ACTIVITY = create("activity");
/**
* Built-in registry for structure types.
* @see io.papermc.paper.registry.keys.StructureTypeKeys
diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java
index e1fb4d8cca6a9c59047b1396f5c40bea957d777a..7e1f769db2a0df7e687a7af2c9329d93ecf00db1 100644
--- a/src/main/java/org/bukkit/Registry.java
+++ b/src/main/java/org/bukkit/Registry.java
@@ -270,6 +270,13 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
Registry<GameEvent> GAME_EVENT = Objects.requireNonNull(Bukkit.getRegistry(GameEvent.class), "No registry present for GameEvent. This is a bug.");
// Paper start
+ /**
+ * Activities.
+ *
+ * @see io.papermc.paper.entity.ai.Activity
+ */
+ Registry<io.papermc.paper.entity.ai.Activity> ACTIVITY = Bukkit.getRegistry(io.papermc.paper.entity.ai.Activity.class);
+
/**
* Configured structures.
* @see io.papermc.paper.world.structure.ConfiguredStructure
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 4ff1b38eb65f97344257204cf018f176f247ed36..4f57f4e0d65a99da3d5ce1ccc5b1534d608c3d36 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2518,4 +2518,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
boolean isOwnedByCurrentRegion(@NotNull Entity entity);
// Paper end - Folia region threading API
+ // Paper start - activities and tasks API
+ @NotNull
+ io.papermc.paper.entity.ai.Tasks getTasks();
+
+ @NotNull
+ <E extends org.bukkit.entity.LivingEntity> io.papermc.paper.entity.ai.Brain<E> getBrain(@NotNull E entity);
+ // Paper end
}