Starting from version 1.21, custom enchantments in Minecraft use a "data-driven" approach. This makes it easier to add simple enchantments, like increasing attack damage, but more challenging to create complex ones. The process involves breaking down enchantments into effect components.
An effect component contains the code that defines the special effects of an enchantment. Minecraft supports various default effects, such as item damage, knockback, and experience.
TIP
Be sure to check if the default Minecraft effects satisfy your needs by visiting the Minecraft Wiki's Enchantment Effect Components page. This guide assumes you understand how to configure "simple" data-driven enchantments and focuses on creating custom enchantment effects that aren't supported by default.
Custom Enchantment Effects
Start by creating an enchantment folder, and within it, create an effect folder. Within that, we'll create the LightningEnchantmentEffect record.
Next, we can create a constructor and override the EnchantmentEntityEffect interface methods. We'll also create a CODEC variable to encode and decode our effect; you can read more about Codecs here.
The bulk of our code will go into the apply() event, which is called when the criteria for your enchantment to work is met. We'll later configure this Effect to be called when an entity is hit, but for now, let's write simple code to strike the target with lightning.
java
public record LightningEnchantmentEffect(LevelBasedValue amount) implements EnchantmentEntityEffect {
public static final MapCodec<LightningEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance ->
instance.group(
LevelBasedValue.CODEC.fieldOf("amount").forGetter(LightningEnchantmentEffect::amount)
).apply(instance, LightningEnchantmentEffect::new)
);
@Override
public void apply(ServerLevel serverLevel, int level, EnchantedItemInUse context, Entity target, Vec3 pos) {
if (target instanceof LivingEntity victim) {
if (context.owner() != null && context.owner() instanceof Player player) {
float numStrikes = this.amount.calculate(level);
for (float i = 0; i < numStrikes; i++) {
BlockPos position = victim.blockPosition();
EntityType.LIGHTNING_BOLT.spawn(serverLevel, position, EntitySpawnReason.TRIGGERED);
}
}
}
}
@Override
public MapCodec<? extends EnchantmentEntityEffect> codec() {
return CODEC;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Here, the amount variable indicates a value scaled to the level of the enchantment. We can use this to modify how effective the enchantment is based on level. In the code above, we are using the level of the enchantment to determine how many lightning strikes are spawned.
Registering the Enchantment Effect
Like every other component of your mod, we'll have to add this EnchantmentEffect to Minecraft's registry. To do so, add a class ModEnchantmentEffects (or whatever you want to name it) and a helper method to register the enchantment. Be sure to call the registerModEnchantmentEffects() in your main class, which contains the onInitialize() method.
java
public class ModEnchantmentEffects {
public static MapCodec<LightningEnchantmentEffect> LIGHTNING_EFFECT = register("lightning_effect", LightningEnchantmentEffect.CODEC);
private static <T extends EnchantmentEntityEffect> MapCodec<T> register(String id, MapCodec<T> codec) {
return Registry.register(BuiltInRegistries.ENCHANTMENT_ENTITY_EFFECT_TYPE, Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, id), codec);
}
public static void registerModEnchantmentEffects() {
ExampleMod.LOGGER.info("Registering EnchantmentEffects for" + ExampleMod.MOD_ID);
}
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Creating the Enchantment
Now we have an enchantment effect! The final step is to create an enchantment that applies our custom effect. We can do this with the data-driven enchantment system by simply adding a JSON file to our mod's resources.
Create the JSON file in data/example-mod/enchantments folder. The name of this file will be the id of the enchantment: thundering.json will become example-mod:thundering.
INFO
For more details about the file format, check out Minecraft Wiki - Enchantment definition.
To quickly generate a custom enchantment, you can use the Misode generator.
For this example we will use the following enchantment definition to add the thundering enchantment using our custom lightning_effect:
json
{
"anvil_cost": 5,
"description": {
"translate": "enchantment.example-mod.thundering"
},
"effects": {
"minecraft:post_attack": [
{
"affected": "victim",
"effect": {
"type": "example-mod:lightning_effect",
"amount": {
"type": "minecraft:linear",
"base": 0.4,
"per_level_above_first": 0.2
}
},
"enchanted": "attacker"
}
]
},
"max_cost": {
"base": 1,
"per_level_above_first": 15
},
"max_level": 3,
"min_cost": {
"base": 1,
"per_level_above_first": 10
},
"slots": [
"hand"
],
"supported_items": "#minecraft:enchantable/weapon",
"weight": 10
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
You should also add translations to your en_us.json file to give your enchantment a readable name:
json
"enchantment.example-mod.thundering": "Thundering",1
You should now have a working custom enchantment effect! Test it by enchanting a weapon with the enchantment and hitting a mob. An example is given in the following video:


