PREREQUISITES
Make sure you've completed the datagen setup process first.
Setup
Before implementing the generator, create the enchantment package in the main source set and add the ModEnchantments class to it. Then add the key method to this new class.
java
private static ResourceKey<Enchantment> key(String path) {
Identifier id = Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, path);
return ResourceKey.create(Registries.ENCHANTMENT, id);
}1
2
3
4
2
3
4
Use this method to create a ResourceKey for your enchantment.
java
public static final ResourceKey<Enchantment> THUNDERING = key("thundering");1
Now, we're ready to add the generator. In the datagen package, create a class that extends FabricDynamicRegistryProvider. In this newly created class, add a constructor that matches super, and implement the configure and getName methods.
java
public class ExampleModEnchantmentGenerator extends FabricDynamicRegistryProvider {
public ExampleModEnchantmentGenerator(FabricDataOutput output, CompletableFuture<HolderLookup.Provider> registriesFuture) {
super(output, registriesFuture);
}
@Override
protected void configure(HolderLookup.Provider registries, Entries entries) {
entries.addAll(registries.lookupOrThrow(Registries.ENCHANTMENT)); // Add all bootstrapped enchantments for the current mod id
}
@Override
public String getName() {
return "Enchantments";
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Then, add the register helper method to the newly created class.
java
private static void register(BootstrapContext<Enchantment> context, ResourceKey<Enchantment> key, Enchantment.Builder builder) {
context.register(key, builder.build(key.identifier()));
}1
2
3
2
3
Now add the bootstrap method. Here, we will be registering the enchantments we want to add to the game.
java
public static void bootstrap(BootstrapContext<Enchantment> context) {
// ...
}1
2
3
2
3
In your DataGeneratorEntrypoint, override the buildRegistry method and register our bootstrap method.
java
@Override
public void buildRegistry(RegistrySetBuilder registryBuilder) {
registryBuilder.add(Registries.ENCHANTMENT, ExampleModEnchantmentGenerator::bootstrap);
}1
2
3
4
2
3
4
Finally, ensure your new generator is registered within the onInitializeDataGenerator method.
java
pack.addProvider(ExampleModEnchantmentGenerator::new);1
Creating the Enchantment
To create the definition for our custom enchantment, we will use the register method in our generator class.
Register your enchantment in the generator's bootstrap method, using the enchantment registered in ModEnchantments.
In this example, we will be using the enchantment effect created in Custom Enchantment Effects, but you can also make use of the vanilla enchantment effects.
java
register(context, ModEnchantments.THUNDERING,
Enchantment.enchantment(
Enchantment.definition(
context.lookup(Registries.ITEM).getOrThrow(ItemTags.WEAPON_ENCHANTABLE), // The items this enchantment can be applied to
10, // The weight / probability of our enchantment being available in the enchanting table
3, // The max level of the enchantment
Enchantment.dynamicCost(1, 10), // The base minimum cost of the enchantment, and the additional cost for every level
Enchantment.dynamicCost(1, 15), // Same as the other dynamic cost, but for the maximum instead
5, // The cost to apply the enchantment in an anvil, in levels
EquipmentSlotGroup.HAND // The slot types in which this enchantment will be able to apply its effects
)
)
.withEffect(
EnchantmentEffectComponents.POST_ATTACK, // The type of effect to be applied
EnchantmentTarget.ATTACKER, // The target to be checked for the enchantment
EnchantmentTarget.VICTIM, // The target to apply the enchantment effect to
new LightningEnchantmentEffect(LevelBasedValue.perLevel(0.4f, 0.2f))
)
);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Now simply run data generation, and your new enchantment will be available in-game!
Effect Conditions
Most enchantment effect types are conditional effects. When adding these effects, it is possible to pass conditions to the withEffect call.
INFO
For an overview of the available condition types and their usage, see the Enchantments class.
java
.withEffect(
// ...
LootItemEntityPropertyCondition.hasProperties(
LootContext.EntityTarget.ATTACKER,
EntityPredicate.Builder.entity().flags(
EntityFlagsPredicate.Builder.flags().setIsFlying(false)
)
)
)1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Multiple Effects
withEffect can be chained to add multiple enchantment effects to a single enchantment. However, this method requires you to specify the effect conditions for every effect.
To instead share the defined conditions and targets across multiple effects, AllOf can be used to merge them into a single effect.
java
AllOf.entityEffects(
new ApplyEntityImpulse(new Vec3(0, 0.2, -1), new Vec3(1, 1, 1), LevelBasedValue.perLevel(0.7f, 0.2f)),
new PlaySoundEffect(List.of(SoundEvents.LUNGE_1), ConstantFloat.of(5), ConstantFloat.of(1))
),1
2
3
4
2
3
4
Note that the method to use depends on the type of effect being added. For example, EnchantmentValueEffect requires AnyOf.valueEffects instead. Differing effect types still require additional withEffect calls.
Enchanting Table
While we have specified the enchantment weight (or chance) in our enchantment definition, it will not appear in the enchanting table by default. To allow our enchantment to be traded by villagers and appear in the enchanting table, we need to add it to the non_treasure tag.
To do this, we can create a tag provider. Create a class that extends FabricTagProvider<Enchantment> in the datagen package. Then implement the constructor with Registries.ENCHANTMENT as the registryKey parameter to super, and create the addTags method.
java
public class ExampleModEnchantmentTagProvider extends FabricTagProvider<Enchantment> {
public ExampleModEnchantmentTagProvider(FabricDataOutput output, CompletableFuture<HolderLookup.Provider> registriesFuture) {
super(output, Registries.ENCHANTMENT, registriesFuture);
}
@Override
protected void addTags(HolderLookup.Provider wrapperLookup) {
// ...
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
We can now add our enchantment to EnchantmentTags.NON_TREASURE by calling the builder from within the addTags method.
java
builder(EnchantmentTags.NON_TREASURE).add(ModEnchantments.THUNDERING);1
Curses
Curses are also implemented using tags. We can use the tag provider from the Enchanting Table section.
In the addTags method, simply add your enchantment to the CURSE tag to mark it as a curse.
java
builder(EnchantmentTags.CURSE).add(ModEnchantments.REPULSION_CURSE);1

