From 07977ba242b7f2fa1336ea79298b7ea50a93f94f Mon Sep 17 00:00:00 2001 From: Paint_Ninja Date: Fri, 6 Dec 2024 18:18:53 +0000 Subject: [PATCH] Deprecate `@ObjectHolder`, add a couple of fast-paths (#10195) --- .../common/asm/ObjectHolderDefinalize.java | 27 ++++++++++++++++--- .../registries/ObjectHolder.java | 12 +++++++++ .../registries/ObjectHolderRegistry.java | 3 +++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java b/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java index 4a4b9e28b6..70cf3bbee9 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java @@ -8,6 +8,7 @@ package net.minecraftforge.fml.common.asm; import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.stream.Collectors; @@ -35,6 +36,9 @@ public class ObjectHolderDefinalize implements ILaunchPluginService { new VanillaObjectHolderData("net.minecraft.core.particles.ParticleTypes", "particle_type", "net.minecraft.core.particles.ParticleType"), new VanillaObjectHolderData("net.minecraft.sounds.SoundEvents", "sound_event", "net.minecraft.sounds.SoundEvent") ).collect(Collectors.toUnmodifiableMap(VanillaObjectHolderData::holderClass, Function.identity())); + private static final Set VANILLA_OBJECT_HOLDER_CLASSES = VANILLA_OBJECT_HOLDERS.keySet().stream() + .map(it -> it.replace('.', '/')) + .collect(Collectors.toUnmodifiableSet()); private static final String OBJECT_HOLDER = "Lnet/minecraftforge/registries/ObjectHolder;"; //Don't directly reference this to prevent class loading. private static final int PUBLIC_STATIC_FINAL_FLAGS = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; @@ -47,9 +51,26 @@ public class ObjectHolderDefinalize implements ILaunchPluginService { private static final EnumSet NAY = EnumSet.noneOf(Phase.class); @Override - public EnumSet handlesClass(Type classType, boolean isEmpty) - { - return isEmpty ? NAY : YAY; + public EnumSet handlesClass(Type classType, boolean isEmpty) { + if (isEmpty) + return NAY; + + // Let's skip processing classes that definitely don't have object holders + String internalName = classType.getInternalName(); + + // Forge classes that aren't in the debug package (that package is used for tests) + if (internalName.startsWith("net/minecraftforge/") && !internalName.substring(18).contains("debug")) + return NAY; + + // Vanilla classes that don't have object holders + if (internalName.startsWith("com/mojang/")) + return NAY; + + // ...except specific ones we added to the VANILLA_OBJECT_HOLDERS map + if (internalName.startsWith("net/minecraft/") && !VANILLA_OBJECT_HOLDER_CLASSES.contains(internalName)) + return NAY; + + return YAY; } private static boolean hasHolder(List lst) { diff --git a/src/main/java/net/minecraftforge/registries/ObjectHolder.java b/src/main/java/net/minecraftforge/registries/ObjectHolder.java index f92b2ecaf3..887f2ddefa 100644 --- a/src/main/java/net/minecraftforge/registries/ObjectHolder.java +++ b/src/main/java/net/minecraftforge/registries/ObjectHolder.java @@ -16,7 +16,19 @@ import java.lang.annotation.Target; /** * ObjectHolder can be used to automatically populate public static final fields with entries * from the registry. These values can then be referred within mod code directly. + * @deprecated Use {@link DeferredRegister} or {@link RegistryObject} instead. Refer to the MDK for more detailed examples. + *
+ * Example usage of alternatives: + *
{@code
+ * // To register something
+ * public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
+ * public static final RegistryObject EXAMPLE_ITEM = ITEMS.register("example_item", () -> new Item(new Item.Properties()));
+ *
+ * // To get a RegistryObject that you didn't register yourself:
+ * public static final RegistryObject DIRT = RegistryObject.create(ResourceLocation.withDefaultNamespace("dirt"), ForgeRegistries.BLOCKS);
+ * }
*/ +@Deprecated(since = "1.21.4", forRemoval = true) @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ObjectHolder diff --git a/src/main/java/net/minecraftforge/registries/ObjectHolderRegistry.java b/src/main/java/net/minecraftforge/registries/ObjectHolderRegistry.java index c2e91a3294..1f4ae73ebc 100644 --- a/src/main/java/net/minecraftforge/registries/ObjectHolderRegistry.java +++ b/src/main/java/net/minecraftforge/registries/ObjectHolderRegistry.java @@ -89,6 +89,9 @@ public class ObjectHolderRegistry .filter(a -> OBJECT_HOLDER.equals(a.annotationType()) || MOD.equals(a.annotationType())) .toList(); + if (annotations.stream().noneMatch(a -> OBJECT_HOLDER.equals(a.annotationType()))) + return; // No object holders found, skip the rest of the processing + Map classModIds = Maps.newHashMap(); Map> classCache = Maps.newHashMap();