diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java index 542fe959fbc..c3bff436589 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/api/item/v1/EnchantmentEvents.java @@ -17,6 +17,7 @@ package net.fabricmc.fabric.api.item.v1; import net.minecraft.core.Holder; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.Enchantment; @@ -76,7 +77,10 @@ private EnchantmentEvents() { } * *

Note: If you wish to modify the exclusive set of the enchantment, consider extending the * {@linkplain net.minecraft.tags.EnchantmentTags relevant tag} through your mod's data pack instead. + * + * @deprecated Use {@link #MODIFY_WITH_LOOKUP} instead, which provides registry access via {@link RegistryOps.RegistryInfoLookup} */ + @Deprecated public static final Event MODIFY = EventFactory.createArrayBacked( Modify.class, callbacks -> (key, builder, source) -> { @@ -86,6 +90,29 @@ private EnchantmentEvents() { } } ); + /** + * An event that allows an {@link Enchantment} to be modified without needing to fully override an enchantment. + * + *

This should only be used to modify the behavior of external enchantments, where 'external' means + * either vanilla or from another mod. For instance, a mod might add a bleed effect to Sharpness (and only Sharpness). + * For your own enchantments, you should simply define them in your mod's data pack. See the + * Enchantment Definition page on the Minecraft Wiki + * for more information. + * + *

Note: If you wish to modify the exclusive set of the enchantment, consider extending the + * {@linkplain net.minecraft.tags.EnchantmentTags relevant tag} through your mod's data pack instead. + * + *

This is the preferred replacement for {@link #MODIFY}, providing access to registry information via {@link RegistryOps.RegistryInfoLookup}. + */ + public static final Event MODIFY_WITH_LOOKUP = EventFactory.createArrayBacked( + ModifyWithLookup.class, + callbacks -> (key, builder, source, registries) -> { + for (ModifyWithLookup callback : callbacks) { + callback.modify(key, builder, source, registries); + } + } + ); + @FunctionalInterface public interface AllowEnchanting { /** @@ -106,6 +133,7 @@ TriState allowEnchanting( } @FunctionalInterface + @Deprecated public interface Modify { /** * Modifies the effects of an {@link Enchantment}. @@ -120,4 +148,22 @@ void modify( EnchantmentSource source ); } + + @FunctionalInterface + public interface ModifyWithLookup { + /** + * Modifies the effects of an {@link Enchantment}. + * + * @param key The ID of the enchantment + * @param builder The enchantment builder + * @param source The source of the enchantment + * @param registryInfoLookup Lookup interface used to access registry information + */ + void modify( + ResourceKey key, + Enchantment.Builder builder, + EnchantmentSource source, + RegistryOps.RegistryInfoLookup registryInfoLookup + ); + } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/EnchantmentUtil.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/EnchantmentUtil.java index d884756c764..f3848b05bd9 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/EnchantmentUtil.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/EnchantmentUtil.java @@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory; import net.minecraft.core.component.DataComponentType; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.server.packs.repository.PackSource; import net.minecraft.server.packs.resources.Resource; @@ -37,9 +38,9 @@ public class EnchantmentUtil { private static final Logger LOGGER = LoggerFactory.getLogger(EnchantmentUtil.class); - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "deprecation"}) @Nullable - public static Enchantment modify(ResourceKey key, Enchantment originalEnchantment, EnchantmentSource source) { + public static Enchantment modify(ResourceKey key, Enchantment originalEnchantment, EnchantmentSource source, RegistryOps.RegistryInfoLookup registryInfoLookup) { Enchantment.Builder builder = Enchantment.enchantment(originalEnchantment.definition()); EnchantmentBuilderAccessor accessor = (EnchantmentBuilderAccessor) builder; BuilderExtensions builderExtensions = (BuilderExtensions) builder; @@ -60,6 +61,7 @@ public static Enchantment modify(ResourceKey key, Enchantment origi builderExtensions.fabric$resetModified(); EnchantmentEvents.MODIFY.invoker().modify(key, builder, source); + EnchantmentEvents.MODIFY_WITH_LOOKUP.invoker().modify(key, builder, source, registryInfoLookup); if (builderExtensions.fabric$didModify()) { LOGGER.debug("Enchantment {} was modified", key.identifier()); diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ResourceManagerRegistryLoadTaskMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ResourceManagerRegistryLoadTaskMixin.java index e00bd302139..a1aba2a70f2 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ResourceManagerRegistryLoadTaskMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ResourceManagerRegistryLoadTaskMixin.java @@ -17,16 +17,22 @@ package net.fabricmc.fabric.mixin.item; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.datafixers.util.Either; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.core.RegistrationInfo; import net.minecraft.resources.RegistryLoadTask; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceManagerRegistryLoadTask; import net.minecraft.server.packs.resources.Resource; @@ -36,11 +42,14 @@ @Mixin(ResourceManagerRegistryLoadTask.class) public class ResourceManagerRegistryLoadTaskMixin { + @Unique + private RegistryOps.RegistryInfoLookup registryInfoLookup; + @WrapOperation(method = "lambda$load$2", at = @At(value = "NEW", target = "net/minecraft/resources/RegistryLoadTask$PendingRegistration")) private RegistryLoadTask.PendingRegistration modify(ResourceKey key, Either value, RegistrationInfo registrationInfo, Operation> original, @Local(argsOnly = true) Resource resource) { if (value.left().isPresent()) { if (value.left().get() instanceof Enchantment enchantment) { - Enchantment modified = EnchantmentUtil.modify((ResourceKey) key, enchantment, EnchantmentUtil.determineSource(resource)); + Enchantment modified = EnchantmentUtil.modify((ResourceKey) key, enchantment, EnchantmentUtil.determineSource(resource), registryInfoLookup); if (modified != null) { // Clear the knownPackInfo to force the server to sync the data pack to the client @@ -52,4 +61,9 @@ private RegistryLoadTask.PendingRegistration modify(ResourceKey key, E return original.call(key, value, registrationInfo); } + + @Inject(method = "load", at = @At("HEAD")) + private void captureRegistries(RegistryOps.RegistryInfoLookup context, Executor executor, CallbackInfoReturnable> cir) { + this.registryInfoLookup = context; + } } diff --git a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomEnchantmentEffectsTest.java b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomEnchantmentEffectsTest.java index fa651e322ea..c4e5bb199b3 100644 --- a/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomEnchantmentEffectsTest.java +++ b/fabric-item-api-v1/src/testmod/java/net/fabricmc/fabric/test/item/CustomEnchantmentEffectsTest.java @@ -23,6 +23,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.EnchantmentTags; import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentEffectComponents; @@ -46,8 +47,8 @@ public class CustomEnchantmentEffectsTest implements ModInitializer { @Override public void onInitialize() { - EnchantmentEvents.MODIFY.register( - (key, builder, source) -> { + EnchantmentEvents.MODIFY_WITH_LOOKUP.register( + (key, builder, source, registries) -> { if (source.isBuiltin() && key == WEIRD_IMPALING) { // make impaling set things on fire builder.withEffect( @@ -70,6 +71,9 @@ public void onInitialize() { .entityType(EntityTypePredicate.of(BuiltInRegistries.ENTITY_TYPE, EntityTypes.ZOMBIE)) ) ); + + // make it exclusive with treasure enchantments + builder.exclusiveWith(registries.lookup(Registries.ENCHANTMENT).orElseThrow().getter().getOrThrow(EnchantmentTags.TREASURE)); } } );