Skip to content

Custom Effect Component Integration

JohnSmith474 edited this page Sep 21, 2026 · 1 revision

While Enchantment Core provides a vast library of effects natively, your mod will likely require registering custom EnchantmentEntityEffect payloads or Item DataComponentType definitions.

Because you are using Enchantment Core, you want your custom effects to be fully configurable. To achieve this, you must seamlessly integrate your standard Vanilla registry calls with the DataTransformerRegistry.

1. Structuring Your Effect

To maintain a clean architecture, define your registry KEY and your JSON keys as public static final Strings directly within your effect record.

If your effect contains any LevelBasedValue properties, you must also provide a LevelBasedKeyProvider. This explicitly lists which properties need dynamic configuration wrappers.

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Set;
import johnsmith.enchantmentcore.api.registry.LevelBasedKeyProvider;
import net.minecraft.world.item.enchantment.LevelBasedValue;

public record AutoSmeltEffect(
        LevelBasedValue additionalToolUsage,
        boolean dropXp
) {
    // 1. Define JSON property keys
    public static final String ADDITIONAL_TOOL_USAGE = "additional_tool_usage";
    public static final String DROP_XP = "drop_xp";

    // 2. Define the Registry Identifier Key
    public static final String KEY = "auto_smelt";

    // 3. Provide the keys mapping to your LevelBasedValues
    public static final LevelBasedKeyProvider KEY_PROVIDER = () -> Set.of(ADDITIONAL_TOOL_USAGE);

    // 4. Build the Codec
    public static final Codec<AutoSmeltEffect> CODEC = RecordCodecBuilder.create(instance ->
            instance.group(
                    LevelBasedValue.CODEC.optionalFieldOf(ADDITIONAL_TOOL_USAGE, LevelBasedValue.constant(0)).forGetter(AutoSmeltEffect::additionalToolUsage),
                    Codec.BOOL.optionalFieldOf(DROP_XP, true).forGetter(AutoSmeltEffect::dropXp)
            ).apply(instance, AutoSmeltEffect::new)
    );
}

2. The Registration Helper

Instead of calling the standard Registry.register directly, create a static helper method in your central registry class. This helper intercepts the LevelBasedKeyProvider and pushes its keys to the DataTransformerRegistry before registering the component to Minecraft.

import com.mojang.serialization.MapCodec;
import johnsmith.enchantmentcore.api.registry.LevelBasedKeyProvider;
import johnsmith.enchantmentcore.registry.DataTransformerRegistry;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect;

public class MyModEffectRegistry {

    // Centralized helper method
    private static <T extends EnchantmentEntityEffect> MapCodec<T> register(
            String name,
            LevelBasedKeyProvider keyProvider,
            MapCodec<T> codec
    ) {
        // Push keys to the transformer automatically!
        for (String key : keyProvider.getLevelBasedKeys()) {
            DataTransformerRegistry.registerEffectProperty(key);
        }
        
        // Register to Vanilla natively
        return Registry.register(
                BuiltInRegistries.ENCHANTMENT_ENTITY_EFFECT_TYPE,
                ResourceLocation.fromNamespaceAndPath("my_mod", name),
                codec
        );
    }

    // Now, registering your effect is completely clean and inherently safe:
    public static final MapCodec<AutoSmeltEffect> AUTO_SMELT = register(
            AutoSmeltEffect.KEY,
            AutoSmeltEffect.KEY_PROVIDER,
            AutoSmeltEffect.CODEC
    );

    public static void initialize() {}
}

This structural pattern ensures that whenever you create a new effect, you never accidentally forget to register its properties for data-driven configuration!

Clone this wiki locally