aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--paper-api-generator/build.gradle.kts6
-rw-r--r--paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java5
-rw-r--r--paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java106
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/Main.java14
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java19
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java12
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java79
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java4
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java4
-rw-r--r--paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java42
-rw-r--r--paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java37
-rw-r--r--patches/api/0004-Code-Generation.patch11
-rw-r--r--patches/api/0442-add-missing-Experimental-annotations.patch40
-rw-r--r--patches/server/0363-Implement-Mob-Goal-API.patch6
-rw-r--r--patches/server/0574-Missing-Entity-API.patch2
16 files changed, 235 insertions, 153 deletions
diff --git a/.gitignore b/.gitignore
index 71fa37fc83..a2adff58b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@ out/
# other stuff
run/
+logs/
Paper-Server
Paper-API
diff --git a/paper-api-generator/build.gradle.kts b/paper-api-generator/build.gradle.kts
index 0147a21349..c3deae7adb 100644
--- a/paper-api-generator/build.gradle.kts
+++ b/paper-api-generator/build.gradle.kts
@@ -16,6 +16,8 @@ dependencies {
implementation(project(":paper-api"))
implementation("io.github.classgraph:classgraph:4.8.47")
implementation("org.jetbrains:annotations:24.0.1")
+ testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
tasks.register<JavaExec>("generate") {
@@ -24,5 +26,9 @@ tasks.register<JavaExec>("generate") {
args(projectDir.toPath().resolve("generated").toString())
}
+tasks.test {
+ useJUnitPlatform()
+}
+
group = "io.papermc.paper"
version = "1.0-SNAPSHOT"
diff --git a/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index c7f171b77d..7ff40b6c33 100644
--- a/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/paper-api-generator/generated/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -1122,7 +1122,8 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
)
GoalKey<Mob> UNIVERSAL_ANGER_RESET = create("universal_anger_reset", Mob.class);
- private static @NotNull GoalKey create(final @NotNull String key, final @NotNull Class clazz) {
- return GoalKey.of(clazz, NamespacedKey.minecraft(key));
+ private static <T extends Mob> @NotNull GoalKey<T> create(final @NotNull String key,
+ final @NotNull Class<T> type) {
+ return GoalKey.of(type, NamespacedKey.minecraft(key));
}
}
diff --git a/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java
index 97ee8b7e15..26ce70c2ab 100644
--- a/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java
+++ b/paper-api-generator/generated/io/papermc/paper/registry/keys/GameEventKeys.java
@@ -125,6 +125,13 @@ public final class GameEventKeys {
public static final TypedKey<GameEvent> ELYTRA_GLIDE = create(key("elytra_glide"));
/**
+ * {@code minecraft:entity_action}
+ *
+ * @apiNote This field is version-dependant and may be removed in future Minecraft versions
+ */
+ public static final TypedKey<GameEvent> ENTITY_ACTION = create(key("entity_action"));
+
+ /**
* {@code minecraft:entity_damage}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
@@ -167,13 +174,6 @@ public final class GameEventKeys {
public static final TypedKey<GameEvent> ENTITY_PLACE = create(key("entity_place"));
/**
- * {@code minecraft:entity_action}
- *
- * @apiNote This field is version-dependant and may be removed in future Minecraft versions
- */
- public static final TypedKey<GameEvent> ENTITY_ACTION = create(key("entity_action"));
-
- /**
* {@code minecraft:equip}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
@@ -286,165 +286,165 @@ public final class GameEventKeys {
public static final TypedKey<GameEvent> PROJECTILE_SHOOT = create(key("projectile_shoot"));
/**
- * {@code minecraft:sculk_sensor_tendrils_clicking}
+ * {@code minecraft:resonate_1}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> SCULK_SENSOR_TENDRILS_CLICKING = create(key("sculk_sensor_tendrils_clicking"));
+ public static final TypedKey<GameEvent> RESONATE_1 = create(key("resonate_1"));
/**
- * {@code minecraft:shear}
+ * {@code minecraft:resonate_2}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> SHEAR = create(key("shear"));
+ public static final TypedKey<GameEvent> RESONATE_2 = create(key("resonate_2"));
/**
- * {@code minecraft:shriek}
+ * {@code minecraft:resonate_3}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> SHRIEK = create(key("shriek"));
+ public static final TypedKey<GameEvent> RESONATE_3 = create(key("resonate_3"));
/**
- * {@code minecraft:splash}
+ * {@code minecraft:resonate_4}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> SPLASH = create(key("splash"));
+ public static final TypedKey<GameEvent> RESONATE_4 = create(key("resonate_4"));
/**
- * {@code minecraft:step}
+ * {@code minecraft:resonate_5}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> STEP = create(key("step"));
+ public static final TypedKey<GameEvent> RESONATE_5 = create(key("resonate_5"));
/**
- * {@code minecraft:swim}
+ * {@code minecraft:resonate_6}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> SWIM = create(key("swim"));
+ public static final TypedKey<GameEvent> RESONATE_6 = create(key("resonate_6"));
/**
- * {@code minecraft:teleport}
+ * {@code minecraft:resonate_7}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> TELEPORT = create(key("teleport"));
+ public static final TypedKey<GameEvent> RESONATE_7 = create(key("resonate_7"));
/**
- * {@code minecraft:unequip}
+ * {@code minecraft:resonate_8}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> UNEQUIP = create(key("unequip"));
+ public static final TypedKey<GameEvent> RESONATE_8 = create(key("resonate_8"));
/**
- * {@code minecraft:resonate_1}
+ * {@code minecraft:resonate_9}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_1 = create(key("resonate_1"));
+ public static final TypedKey<GameEvent> RESONATE_9 = create(key("resonate_9"));
/**
- * {@code minecraft:resonate_2}
+ * {@code minecraft:resonate_10}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_2 = create(key("resonate_2"));
+ public static final TypedKey<GameEvent> RESONATE_10 = create(key("resonate_10"));
/**
- * {@code minecraft:resonate_3}
+ * {@code minecraft:resonate_11}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_3 = create(key("resonate_3"));
+ public static final TypedKey<GameEvent> RESONATE_11 = create(key("resonate_11"));
/**
- * {@code minecraft:resonate_4}
+ * {@code minecraft:resonate_12}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_4 = create(key("resonate_4"));
+ public static final TypedKey<GameEvent> RESONATE_12 = create(key("resonate_12"));
/**
- * {@code minecraft:resonate_5}
+ * {@code minecraft:resonate_13}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_5 = create(key("resonate_5"));
+ public static final TypedKey<GameEvent> RESONATE_13 = create(key("resonate_13"));
/**
- * {@code minecraft:resonate_6}
+ * {@code minecraft:resonate_14}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_6 = create(key("resonate_6"));
+ public static final TypedKey<GameEvent> RESONATE_14 = create(key("resonate_14"));
/**
- * {@code minecraft:resonate_7}
+ * {@code minecraft:resonate_15}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_7 = create(key("resonate_7"));
+ public static final TypedKey<GameEvent> RESONATE_15 = create(key("resonate_15"));
/**
- * {@code minecraft:resonate_8}
+ * {@code minecraft:sculk_sensor_tendrils_clicking}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_8 = create(key("resonate_8"));
+ public static final TypedKey<GameEvent> SCULK_SENSOR_TENDRILS_CLICKING = create(key("sculk_sensor_tendrils_clicking"));
/**
- * {@code minecraft:resonate_9}
+ * {@code minecraft:shear}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_9 = create(key("resonate_9"));
+ public static final TypedKey<GameEvent> SHEAR = create(key("shear"));
/**
- * {@code minecraft:resonate_10}
+ * {@code minecraft:shriek}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_10 = create(key("resonate_10"));
+ public static final TypedKey<GameEvent> SHRIEK = create(key("shriek"));
/**
- * {@code minecraft:resonate_11}
+ * {@code minecraft:splash}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_11 = create(key("resonate_11"));
+ public static final TypedKey<GameEvent> SPLASH = create(key("splash"));
/**
- * {@code minecraft:resonate_12}
+ * {@code minecraft:step}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_12 = create(key("resonate_12"));
+ public static final TypedKey<GameEvent> STEP = create(key("step"));
/**
- * {@code minecraft:resonate_13}
+ * {@code minecraft:swim}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_13 = create(key("resonate_13"));
+ public static final TypedKey<GameEvent> SWIM = create(key("swim"));
/**
- * {@code minecraft:resonate_14}
+ * {@code minecraft:teleport}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_14 = create(key("resonate_14"));
+ public static final TypedKey<GameEvent> TELEPORT = create(key("teleport"));
/**
- * {@code minecraft:resonate_15}
+ * {@code minecraft:unequip}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
- public static final TypedKey<GameEvent> RESONATE_15 = create(key("resonate_15"));
+ public static final TypedKey<GameEvent> UNEQUIP = create(key("unequip"));
private GameEventKeys() {
}
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/Main.java b/paper-api-generator/src/main/java/io/papermc/generator/Main.java
index e02f55871f..fa2b05e94c 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/Main.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/Main.java
@@ -1,20 +1,14 @@
package io.papermc.generator;
import com.mojang.logging.LogUtils;
-import io.papermc.generator.types.GeneratedKeyType;
import io.papermc.generator.types.SourceGenerator;
-import io.papermc.paper.registry.RegistryKey;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.List;
import net.minecraft.SharedConstants;
import net.minecraft.core.LayeredRegistryAccess;
-import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
-import net.minecraft.core.registries.Registries;
import net.minecraft.resources.RegistryDataLoader;
-import net.minecraft.resources.ResourceKey;
import net.minecraft.server.Bootstrap;
import net.minecraft.server.RegistryLayer;
import net.minecraft.server.WorldLoader;
@@ -24,12 +18,6 @@ import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.server.packs.repository.ServerPacksSource;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import org.apache.commons.io.file.PathUtils;
-import org.bukkit.GameEvent;
-import org.bukkit.block.Biome;
-import org.bukkit.generator.structure.Structure;
-import org.bukkit.generator.structure.StructureType;
-import org.bukkit.inventory.meta.trim.TrimMaterial;
-import org.bukkit.inventory.meta.trim.TrimPattern;
import org.slf4j.Logger;
public final class Main {
@@ -40,6 +28,8 @@ public final class Main {
static {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
+ Bootstrap.validate();
+
final PackRepository resourceRepository = ServerPacksSource.createVanillaTrustedRepository();
resourceRepository.reload();
final MultiPackResourceManager resourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, resourceRepository.getAvailablePacks().stream().map(Pack::open).toList());
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java
index b5ad821c1c..ba27aa640d 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/types/GeneratedKeyType.java
@@ -10,6 +10,7 @@ import com.squareup.javapoet.TypeSpec;
import io.papermc.generator.Main;
import io.papermc.generator.utils.Annotations;
import io.papermc.generator.utils.CollectingContext;
+import io.papermc.generator.utils.Formatting;
import io.papermc.generator.utils.Javadocs;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
@@ -19,14 +20,15 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import net.kyori.adventure.key.Key;
+import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.data.registries.UpdateOneTwentyOneRegistries;
import net.minecraft.resources.ResourceKey;
+import org.bukkit.MinecraftExperimental;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;
@@ -115,30 +117,31 @@ public class GeneratedKeyType<T, A> extends SimpleGenerator {
final TypeName typedKey = ParameterizedTypeName.get(TypedKey.class, this.apiType);
final TypeSpec.Builder typeBuilder = this.keyHolderType();
- typeBuilder.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO experimental API
final MethodSpec.Builder createMethod = this.createMethod(typedKey);
final Registry<T> registry = Main.REGISTRY_ACCESS.registryOrThrow(this.registryKey);
final List<ResourceKey<T>> experimental = this.collectExperimentalKeys(registry);
boolean allExperimental = true;
- for (final T value : registry) {
- final ResourceKey<T> key = registry.getResourceKey(value).orElseThrow();
+ for (final Holder.Reference<T> reference : registry.holders().sorted(Formatting.alphabeticKeyOrder(reference -> reference.key().location().getPath())).toList()) {
+ final ResourceKey<T> key = reference.key();
final String keyPath = key.location().getPath();
- final String fieldName = keyPath.toUpperCase(Locale.ENGLISH).replaceAll("[.-/]", "_"); // replace invalid field name chars
+ final String fieldName = Formatting.formatKeyAsField(keyPath);
final FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL)
.initializer("$N(key($S))", createMethod.build(), keyPath)
.addJavadoc(Javadocs.getVersionDependentField("{@code $L}"), key.location().toString());
if (experimental.contains(key)) {
- fieldBuilder.addAnnotations(experimentalAnnotations("MinecraftExperimental.Requires.UPDATE_1_21"));
+ fieldBuilder.addAnnotations(experimentalAnnotations(MinecraftExperimental.Requires.UPDATE_1_21));
} else {
allExperimental = false;
}
typeBuilder.addField(fieldBuilder.build());
}
if (allExperimental) {
- typeBuilder.addAnnotations(experimentalAnnotations("MinecraftExperimental.Requires.UPDATE_1_21"));
- createMethod.addAnnotations(experimentalAnnotations("MinecraftExperimental.Requires.UPDATE_1_21"));
+ typeBuilder.addAnnotations(experimentalAnnotations(MinecraftExperimental.Requires.UPDATE_1_21));
+ createMethod.addAnnotations(experimentalAnnotations(MinecraftExperimental.Requires.UPDATE_1_21));
+ } else {
+ typeBuilder.addAnnotation(EXPERIMENTAL_API_ANNOTATION); // TODO experimental API
}
return typeBuilder.addMethod(createMethod.build()).build();
}
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java b/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java
index 76edecd9ff..b4c1095c84 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/types/SimpleGenerator.java
@@ -5,7 +5,6 @@ import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.nio.file.Path;
public abstract class SimpleGenerator implements SourceGenerator {
@@ -24,14 +23,13 @@ public abstract class SimpleGenerator implements SourceGenerator {
@Override
public void writeToFile(Path parent) throws IOException {
- Path packagePath = parent.resolve(this.packageName.replace('.', '/'));
- Files.createDirectories(packagePath);
- JavaFile.Builder builder = JavaFile.builder(this.packageName, this.getTypeSpec())
- .indent(" ");
- this.file(builder);
+ JavaFile.Builder builder = JavaFile.builder(this.packageName, this.getTypeSpec());
+ this.file(builder)
+ .indent(" ")
+ .skipJavaLangImports(true);
- Files.writeString(packagePath.resolve(this.className + ".java"), this.file(builder).build().toString(), StandardCharsets.UTF_8);
+ builder.build().writeTo(parent, StandardCharsets.UTF_8);
}
}
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java
index 649490b5b0..7f94034424 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalGenerator.java
@@ -2,7 +2,6 @@ package io.papermc.generator.types.goal;
import com.destroystokyo.paper.entity.RangedEntity;
import com.destroystokyo.paper.entity.ai.GoalKey;
-import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
@@ -19,12 +18,7 @@ import io.papermc.generator.utils.Annotations;
import io.papermc.generator.utils.Formatting;
import io.papermc.generator.utils.Javadocs;
import java.util.Comparator;
-import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
import javax.lang.model.element.Modifier;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.goal.WrappedGoal;
@@ -65,9 +59,13 @@ import org.bukkit.entity.Vindicator;
import org.bukkit.entity.WanderingTrader;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
-import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+
@DefaultQualifier(NonNull.class)
public class MobGoalGenerator extends SimpleGenerator {
@@ -168,57 +166,53 @@ public class MobGoalGenerator extends SimpleGenerator {
@Override
protected TypeSpec getTypeSpec() {
- TypeName clazzType = TypeName.get(Class.class)
- .annotated(Annotations.NOT_NULL);
- TypeName keyType = TypeName.get(String.class)
- .annotated(Annotations.NOT_NULL);
-
- MethodSpec.Builder createMethod = MethodSpec.methodBuilder("create")
- .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
- .addParameter(ParameterSpec.builder(keyType, "key", Modifier.FINAL)
- .build()
- )
- .addParameter(ParameterSpec.builder(clazzType, "clazz", Modifier.FINAL)
- .build()
- )
- .addCode("return $T.of(clazz, $T.minecraft(key));", GoalKey.class, NamespacedKey.class)
- .returns(ParameterizedTypeName.get(GoalKey.class).annotated(Annotations.NOT_NULL));
-
-
TypeVariableName type = TypeVariableName.get("T", Mob.class);
TypeSpec.Builder typeBuilder = TypeSpec.interfaceBuilder(this.className)
.addSuperinterface(ParameterizedTypeName.get(ClassName.get(com.destroystokyo.paper.entity.ai.Goal.class), type))
- .addModifiers(Modifier.PUBLIC)
+ .addModifiers(PUBLIC)
.addTypeVariable(type)
.addAnnotations(Annotations.CLASS_HEADER)
.addJavadoc(CLASS_HEADER);
+ TypeName mobType = ParameterizedTypeName.get(ClassName.get(Class.class), type)
+ .annotated(Annotations.NOT_NULL);
+ TypeName keyType = TypeName.get(String.class)
+ .annotated(Annotations.NOT_NULL);
- List<Class<?>> classes;
+ ParameterSpec keyParam = ParameterSpec.builder(keyType, "key", FINAL).build();
+ ParameterSpec typeParam = ParameterSpec.builder(mobType, "type", FINAL).build();
+ MethodSpec.Builder createMethod = MethodSpec.methodBuilder("create")
+ .addModifiers(PRIVATE, STATIC)
+ .addParameter(keyParam)
+ .addParameter(typeParam)
+ .addCode("return $T.of($N, $T.minecraft($N));", GoalKey.class, typeParam, NamespacedKey.class, keyParam)
+ .addTypeVariable(type)
+ .returns(ParameterizedTypeName.get(ClassName.get(GoalKey.class), type).annotated(Annotations.NOT_NULL));
+
+ List<Class<Goal>> classes;
try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) {
- classes = scanResult.getSubclasses(net.minecraft.world.entity.ai.goal.Goal.class.getName()).loadClasses();
+ classes = scanResult.getSubclasses(Goal.class.getName()).loadClasses(Goal.class);
}
- List<VanillaGoalKey> vanillaNames = classes.stream()
+ List<GoalKey<Mob>> vanillaNames = classes.stream()
.filter(clazz -> !java.lang.reflect.Modifier.isAbstract(clazz.getModifiers()))
.filter(clazz -> !WrappedGoal.class.equals(clazz)) // TODO - properly fix
- .map(goalClass -> new VanillaGoalKey(goalClass, MobGoalNames.getKey(goalClass.getName(), (Class<? extends Goal>) goalClass)))
- .filter((key) -> !MobGoalNames.isIgnored(key.key().getNamespacedKey().getKey()))
- .sorted(Comparator.<VanillaGoalKey, String>comparing(o -> o.key().getEntityClass().getSimpleName())
- .thenComparing(vanillaGoalKey -> vanillaGoalKey.key.getNamespacedKey().getKey())
+ .map(goalClass -> MobGoalNames.getKey(goalClass.getName(), goalClass))
+ .filter((key) -> !MobGoalNames.isIgnored(key.getNamespacedKey().getKey()))
+ .sorted(Comparator.<GoalKey<?>, String>comparing(o -> o.getEntityClass().getSimpleName())
+ .thenComparing(vanillaGoalKey -> vanillaGoalKey.getNamespacedKey().getKey())
)
.toList();
- for (final VanillaGoalKey vanillaGoalKey : vanillaNames) {
- GoalKey<?> value = vanillaGoalKey.key();
- TypeName typedKey = ParameterizedTypeName.get(GoalKey.class, value.getEntityClass());
- NamespacedKey key = value.getNamespacedKey();
+ for (final GoalKey<?> goalKey : vanillaNames) {
+ TypeName typedKey = ParameterizedTypeName.get(GoalKey.class, goalKey.getEntityClass());
+ NamespacedKey key = goalKey.getNamespacedKey();
String keyPath = key.getKey();
- String fieldName = Formatting.formatKeyAsField(key);
- FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
- .initializer("$N($S, $T.class)", createMethod.build(), keyPath, value.getEntityClass());
+ String fieldName = Formatting.formatKeyAsField(keyPath);
+ FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL)
+ .initializer("$N($S, $T.class)", createMethod.build(), keyPath, goalKey.getEntityClass());
typeBuilder.addField(fieldBuilder.build());
}
@@ -227,8 +221,8 @@ public class MobGoalGenerator extends SimpleGenerator {
NamespacedKey key = NamespacedKey.minecraft(value.entryName);
String keyPath = key.getKey();
- String fieldName = Formatting.formatKeyAsField(key);
- FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
+ String fieldName = Formatting.formatKeyAsField(keyPath);
+ FieldSpec.Builder fieldBuilder = FieldSpec.builder(typedKey, fieldName, PUBLIC, STATIC, FINAL)
.addAnnotation(Annotations.deprecatedVersioned(value.removedVersion, value.removalVersion != null))
.initializer("$N($S, $T.class)", createMethod.build(), keyPath, value.entity);
@@ -251,9 +245,6 @@ public class MobGoalGenerator extends SimpleGenerator {
.skipJavaLangImports(true);
}
- record VanillaGoalKey(Class<?> clazz, GoalKey<?> key) {
- }
-
record DeprecatedEntry(Class<?> entity, String entryName, @Nullable String removalVersion,
@Nullable String removedVersion) {
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java
index 37506e3f84..2ad5e0ac06 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/types/goal/MobGoalNames.java
@@ -126,7 +126,7 @@ import java.util.Set;
public class MobGoalNames {
private static final Map<Class<? extends Goal>, Class<? extends Mob>> entityClassCache = new HashMap<>();
- private static final Map<Class<? extends net.minecraft.world.entity.Mob>, Class<? extends Mob>> bukkitMap = new HashMap<>();
+ public static final Map<Class<? extends net.minecraft.world.entity.Mob>, Class<? extends Mob>> bukkitMap = new HashMap<>();
static {
@@ -233,6 +233,8 @@ public class MobGoalNames {
bukkitMap.put(net.minecraft.world.entity.animal.allay.Allay.class, org.bukkit.entity.Allay.class);
bukkitMap.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, org.bukkit.entity.Sniffer.class);
bukkitMap.put(net.minecraft.world.entity.monster.breeze.Breeze.class, org.bukkit.entity.Breeze.class);
+ bukkitMap.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, org.bukkit.entity.Armadillo.class);
+ bukkitMap.put(net.minecraft.world.entity.monster.Bogged.class, org.bukkit.entity.Bogged.class);
//</editor-fold>
}
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java
index 5c82a94e7a..a00a682330 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/Annotations.java
@@ -12,11 +12,11 @@ import org.jetbrains.annotations.Nullable;
public final class Annotations {
- public static List<AnnotationSpec> experimentalAnnotations(final String version) {
+ public static List<AnnotationSpec> experimentalAnnotations(final MinecraftExperimental.Requires requiredFeatureFlag) {
return List.of(
AnnotationSpec.builder(ApiStatus.Experimental.class).build(),
AnnotationSpec.builder(MinecraftExperimental.class)
- .addMember("value", "$L", version)
+ .addMember("value", "$T.$L", MinecraftExperimental.Requires.class, requiredFeatureFlag.name())
.build()
);
}
diff --git a/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java b/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java
index f4b07411a4..a6c88a8a14 100644
--- a/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java
+++ b/paper-api-generator/src/main/java/io/papermc/generator/utils/Formatting.java
@@ -1,13 +1,47 @@
package io.papermc.generator.utils;
-import net.kyori.adventure.key.Key;
-
+import org.apache.commons.lang3.math.NumberUtils;
+import java.util.Comparator;
import java.util.Locale;
+import java.util.OptionalInt;
+import java.util.function.Function;
+import java.util.regex.Pattern;
public final class Formatting {
- public static String formatKeyAsField(Key key) {
- return key.value().toUpperCase(Locale.ENGLISH).replaceAll("[.-/]", "_"); // replace invalid field name chars
+ private static final Pattern ILLEGAL_FIELD_CHARACTERS = Pattern.compile("[.-/]");
+
+ public static String formatKeyAsField(String path) {
+ return ILLEGAL_FIELD_CHARACTERS.matcher(path.toUpperCase(Locale.ENGLISH)).replaceAll("_");
+ }
+
+ public static Comparator<String> ALPHABETIC_KEY_ORDER = alphabeticKeyOrder(path -> path);
+
+ public static <T> Comparator<T> alphabeticKeyOrder(Function<T, String> mapper) {
+ return (o1, o2) -> {
+ String path1 = mapper.apply(o1);
+ String path2 = mapper.apply(o2);
+
+ OptionalInt trailingInt1 = tryParseTrailingInt(path1);
+ OptionalInt trailingInt2 = tryParseTrailingInt(path2);
+
+ if (trailingInt1.isPresent() && trailingInt2.isPresent()) {
+ return Integer.compare(trailingInt1.getAsInt(), trailingInt2.getAsInt());
+ }
+
+ return path1.compareTo(path2);
+ };
+ }
+
+ private static OptionalInt tryParseTrailingInt(String path) {
+ int delimiterIndex = path.lastIndexOf('_');
+ if (delimiterIndex != -1) {
+ String score = path.substring(delimiterIndex + 1);
+ if (NumberUtils.isDigits(score)) {
+ return OptionalInt.of(Integer.parseInt(score));
+ }
+ }
+ return OptionalInt.empty();
}
private Formatting() {
diff --git a/paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java b/paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java
new file mode 100644
index 0000000000..9bc9f6b400
--- /dev/null
+++ b/paper-api-generator/src/test/java/io/papermc/generator/MobGoalConverterTest.java
@@ -0,0 +1,37 @@
+package io.papermc.generator;
+
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ScanResult;
+import io.papermc.generator.types.goal.MobGoalNames;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.Mob;
+import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class MobGoalConverterTest {
+
+ @Test
+ public void testBukkitMap() {
+ final List<Class<Mob>> classes;
+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages(Entity.class.getPackageName()).scan()) {
+ classes = scanResult.getSubclasses(Mob.class.getName()).loadClasses(Mob.class);
+ }
+
+ assertFalse(classes.isEmpty(), "There are supposed to be more than 0 mob classes!");
+
+ List<String> missingClasses = new ArrayList<>();
+ for (Class<Mob> nmsClass : classes) {
+ if (!MobGoalNames.bukkitMap.containsKey(nmsClass)) {
+ missingClasses.add(nmsClass.getCanonicalName());
+ }
+ }
+
+ if (!missingClasses.isEmpty()) {
+ fail("Missing some entity classes in the bukkit map: " + String.join(", ", missingClasses));
+ }
+ }
+}
diff --git a/patches/api/0004-Code-Generation.patch b/patches/api/0004-Code-Generation.patch
index 2e1f5eb6a3..edbc6ff3ef 100644
--- a/patches/api/0004-Code-Generation.patch
+++ b/patches/api/0004-Code-Generation.patch
@@ -246,13 +246,14 @@ index 0000000000000000000000000000000000000000..3c3fd73f7742bb8602e2f9164dd4c120
+record TypedKeyImpl<T extends Keyed>(@NotNull Key key, @NotNull RegistryKey<T> registryKey) implements TypedKey<T> {
+}
diff --git a/src/main/java/org/bukkit/MinecraftExperimental.java b/src/main/java/org/bukkit/MinecraftExperimental.java
-index b6f4810e387c22c4a70609ea1d605130245689a5..74d5c5e516715e7876b81bfa997d80edbe48476d 100644
+index b6f4810e387c22c4a70609ea1d605130245689a5..03824ae54e1bdb8b14f79b3c5e0294ae725e43f8 100644
--- a/src/main/java/org/bukkit/MinecraftExperimental.java
+++ b/src/main/java/org/bukkit/MinecraftExperimental.java
-@@ -49,4 +49,6 @@ public @interface MinecraftExperimental {
+@@ -47,6 +47,6 @@ public @interface MinecraftExperimental {
+ @ApiStatus.Internal
+ public enum Requires {
- UPDATE_1_21
+- UPDATE_1_21
++ UPDATE_1_21, BUNDLE, TRADE_REBALANCE // Paper
}
-+
-+ String desc() default ""; // Paper
}
diff --git a/patches/api/0442-add-missing-Experimental-annotations.patch b/patches/api/0442-add-missing-Experimental-annotations.patch
index 9c46d14fa0..89d99d97d4 100644
--- a/patches/api/0442-add-missing-Experimental-annotations.patch
+++ b/patches/api/0442-add-missing-Experimental-annotations.patch
@@ -27,7 +27,7 @@ index 6b68c92ec894451d99ded3e3df5965cb31d68ed2..fd5e433f930963c102c9c977523a0036
public static final FeatureFlag UPDATE_121 = Bukkit.getUnsafe().getFeatureFlag(NamespacedKey.minecraft("update_1_21"));
}
diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
-index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d2442a832 100644
+index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..c892610f2127f7415c287fa007ddda0aa99af28d 100644
--- a/src/main/java/org/bukkit/Material.java
+++ b/src/main/java/org/bukkit/Material.java
@@ -146,54 +146,67 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
@@ -240,15 +240,16 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
WAXED_OXIDIZED_COPPER_TRAPDOOR(21450, TrapDoor.class),
/**
* BlockData: {@link Gate}
-@@ -2531,6 +2569,7 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -2531,6 +2569,8 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
EGG(21603, 16),
COMPASS(24139),
RECOVERY_COMPASS(12710),
++ @MinecraftExperimental(Requires.BUNDLE) // Paper - add missing annotation
+ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation
BUNDLE(16835, 1),
FISHING_ROD(4167, 1, 64),
CLOCK(14980),
-@@ -2637,6 +2676,7 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -2637,6 +2677,7 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
* BlockData: {@link Crafter}
*/
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -256,7 +257,7 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
CRAFTER(25243, Crafter.class),
FILLED_MAP(23504),
SHEARS(27971, 1, 238),
-@@ -2677,8 +2717,10 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -2677,8 +2718,10 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
BEE_SPAWN_EGG(22924),
BLAZE_SPAWN_EGG(4759),
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -267,7 +268,7 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
BREEZE_SPAWN_EGG(7580),
CAT_SPAWN_EGG(29583),
CAMEL_SPAWN_EGG(14760),
-@@ -2755,10 +2797,12 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -2755,10 +2798,12 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
EXPERIENCE_BOTTLE(12858),
FIRE_CHARGE(4842),
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -280,7 +281,7 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
MACE(4771, 1, 250),
ITEM_FRAME(27318),
GLOW_ITEM_FRAME(26473),
-@@ -3157,8 +3201,10 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -3157,8 +3202,10 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
RAISER_ARMOR_TRIM_SMITHING_TEMPLATE(29116),
HOST_ARMOR_TRIM_SMITHING_TEMPLATE(12165),
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -291,7 +292,7 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
BOLT_ARMOR_TRIM_SMITHING_TEMPLATE(9698),
ANGLER_POTTERY_SHERD(9952),
ARCHER_POTTERY_SHERD(21629),
-@@ -3169,9 +3215,11 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -3169,9 +3216,11 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
DANGER_POTTERY_SHERD(30506),
EXPLORER_POTTERY_SHERD(5124),
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -303,7 +304,7 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
GUSTER_POTTERY_SHERD(28193),
HEART_POTTERY_SHERD(17607),
HEARTBREAK_POTTERY_SHERD(21108),
-@@ -3181,6 +3229,7 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -3181,6 +3230,7 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
PLENTY_POTTERY_SHERD(28236),
PRIZE_POTTERY_SHERD(4341),
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -311,7 +312,7 @@ index 8283eccf2578bae50a4c6fd86318e0d5f7cf09df..6ebc5da2b47b005b836927621f3b929d
SCRAPE_POTTERY_SHERD(30034),
SHEAF_POTTERY_SHERD(23652),
SHELTER_POTTERY_SHERD(28390),
-@@ -3190,99 +3239,121 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -3190,99 +3240,121 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
* BlockData: {@link Waterlogged}
*/
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -485,7 +486,7 @@ index b0ccd263cabe911d43cc13261011b64cacaeb7bb..82d75010cc86bbbbb9c094c2bac5e570
/**
* Uses {@link BlockData} as DataType
diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java
-index 375172e05a78611deb3003f780867516cb6cd1a4..b31a8ff47e28440b5e91ddd2fe3f07fd7219d4df 100644
+index 375172e05a78611deb3003f780867516cb6cd1a4..7c39a281a38b412a989dbdf3d12e826ee6eda714 100644
--- a/src/main/java/org/bukkit/Sound.java
+++ b/src/main/java/org/bukkit/Sound.java
@@ -221,40 +221,56 @@ public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Pa
@@ -796,7 +797,22 @@ index 375172e05a78611deb3003f780867516cb6cd1a4..b31a8ff47e28440b5e91ddd2fe3f07fd
EVENT_MOB_EFFECT_TRIAL_OMEN("event.mob_effect.trial_omen"),
EVENT_RAID_HORN("event.raid.horn"),
INTENTIONALLY_EMPTY("intentionally_empty"),
-@@ -1624,13 +1709,17 @@ public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Pa
+@@ -1591,8 +1676,14 @@ public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Pa
+ ITEM_BUCKET_FILL_LAVA("item.bucket.fill_lava"),
+ ITEM_BUCKET_FILL_POWDER_SNOW("item.bucket.fill_powder_snow"),
+ ITEM_BUCKET_FILL_TADPOLE("item.bucket.fill_tadpole"),
++ @MinecraftExperimental(Requires.BUNDLE) // Paper - add missing annotation
++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation
+ ITEM_BUNDLE_DROP_CONTENTS("item.bundle.drop_contents"),
++ @MinecraftExperimental(Requires.BUNDLE) // Paper - add missing annotation
++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation
+ ITEM_BUNDLE_INSERT("item.bundle.insert"),
++ @MinecraftExperimental(Requires.BUNDLE) // Paper - add missing annotation
++ @org.jetbrains.annotations.ApiStatus.Experimental // Paper - add missing annotation
+ ITEM_BUNDLE_REMOVE_ONE("item.bundle.remove_one"),
+ ITEM_CHORUS_FRUIT_TELEPORT("item.chorus_fruit.teleport"),
+ ITEM_CROP_PLANT("item.crop.plant"),
+@@ -1624,13 +1715,17 @@ public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Pa
ITEM_INK_SAC_USE("item.ink_sac.use"),
ITEM_LODESTONE_COMPASS_LOCK("item.lodestone_compass.lock"),
@MinecraftExperimental(Requires.UPDATE_1_21)
@@ -814,7 +830,7 @@ index 375172e05a78611deb3003f780867516cb6cd1a4..b31a8ff47e28440b5e91ddd2fe3f07fd
ITEM_OMINOUS_BOTTLE_DISPOSE("item.ominous_bottle.dispose"),
ITEM_SHIELD_BLOCK("item.shield.block"),
ITEM_SHIELD_BREAK("item.shield.break"),
-@@ -1647,12 +1736,16 @@ public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Pa
+@@ -1647,12 +1742,16 @@ public enum Sound implements Keyed, net.kyori.adventure.sound.Sound.Type { // Pa
ITEM_TRIDENT_THROW("item.trident.throw"),
ITEM_TRIDENT_THUNDER("item.trident.thunder"),
@MinecraftExperimental(Requires.UPDATE_1_21)
diff --git a/patches/server/0363-Implement-Mob-Goal-API.patch b/patches/server/0363-Implement-Mob-Goal-API.patch
index 33bb7d6d59..50b5ac2812 100644
--- a/patches/server/0363-Implement-Mob-Goal-API.patch
+++ b/patches/server/0363-Implement-Mob-Goal-API.patch
@@ -18,10 +18,10 @@ index b1b7d9b72c9f79fe2cfcde47be35a7e73b35d6ff..81b42b378f2d44ce1ffba5ee3f50aad3
testImplementation("org.mockito:mockito-core:5.11.0")
diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
new file mode 100644
-index 0000000000000000000000000000000000000000..74778e5089814dd3a28e91738e82dfd7b8eb8d4c
+index 0000000000000000000000000000000000000000..55e85267c7cbd8be5d2da212e33c43fb353f2e12
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
-@@ -0,0 +1,376 @@
+@@ -0,0 +1,378 @@
+package com.destroystokyo.paper.entity.ai;
+
+import com.destroystokyo.paper.entity.RangedEntity;
@@ -270,6 +270,8 @@ index 0000000000000000000000000000000000000000..74778e5089814dd3a28e91738e82dfd7
+ bukkitMap.put(net.minecraft.world.entity.animal.allay.Allay.class, org.bukkit.entity.Allay.class);
+ bukkitMap.put(net.minecraft.world.entity.animal.sniffer.Sniffer.class, org.bukkit.entity.Sniffer.class);
+ bukkitMap.put(Breeze.class, org.bukkit.entity.Breeze.class);
++ bukkitMap.put(net.minecraft.world.entity.animal.armadillo.Armadillo.class, org.bukkit.entity.Armadillo.class);
++ bukkitMap.put(net.minecraft.world.entity.monster.Bogged.class, org.bukkit.entity.Bogged.class);
+ }
+
+ public static String getUsableName(Class<?> clazz) {
diff --git a/patches/server/0574-Missing-Entity-API.patch b/patches/server/0574-Missing-Entity-API.patch
index 1e466fb30d..0f3d205a48 100644
--- a/patches/server/0574-Missing-Entity-API.patch
+++ b/patches/server/0574-Missing-Entity-API.patch
@@ -44,7 +44,7 @@ Co-authored-by: FireInstall <[email protected]>
Co-authored-by: maxcom1 <[email protected]>
diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
-index 74778e5089814dd3a28e91738e82dfd7b8eb8d4c..86933746b211a8fa7006b6854c42234a78a37843 100644
+index 55e85267c7cbd8be5d2da212e33c43fb353f2e12..c72d6bccf7d72d08d388c65936a89c92261c7860 100644
--- a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java
@@ -165,7 +165,7 @@ public class MobGoalHelper {