Data Driven Enchantments are something that was introduced by 1.21, it is a total rewrite to how enchantments are implemented through code, to make them customisable to an end user through datapack. This guide's examples are in Mojmap, which may not be the mappings you are using. I will provide Yarn names for important classes, but otherwise, I'd recommend Linkie for remapping class/method/field names.
Data driven enchantments belong in the data/<namespace>/enchantment/
folder.
I'd highly recommend datagen as enchantment JSON can get complicated pretty quickly, especially with predicates and all, explaining datagen is out of scope for this guide, but it will help knowing how to use it.
Enchantments in data are structured as follows:
Field Name | Type | Default | Description |
---|---|---|---|
effects |
Array of Enchantment Effect Components | Determines what the enchantment does. Formatted by using the name of the effect, then the object of the effect. Search through the EnchantmentEffectComponents (Mojmap)/EnchantmentEffectComponentTypes (Yarn) class to see what the built-in ones are. | |
description |
Component (Mojmap)/Text (Yarn) | (If datagenning, this will default to the enchantment's lang name) | The name of the enchantment shown to players, say Smite, or Riptide. |
max_level |
Integer (1-255) | The maximum level of the enchantment. | |
exclusive_set |
Array of Enchantment IDs or Enchantment Tag | The enchantments that this enchantment is incompatible with. This field only needs to be on one of the enchantments to work, as seen with Infinity and Mending. | |
slots |
Array of EquipmentSlots | The slots that this enchantment is effective in. | |
supported_items |
Array of Item IDs or Item Tag | The items that this enchantment supports. | |
primary_items |
Array of Item IDs or Item Tag | optional |
If set, the only items that this enchantment will appear on in an enchanting table. |
min_cost |
Enchantment Cost | Determines the minimum cost of the enchantment inside the enchanting table, as well as the returned XP from a Grindstone, accepts base and per_level_above_first values. |
|
max_cost |
Enchantment Cost | Determines the maximum cost of the enchantment inside the enchanting table, accepts base and per_level_above_first values. |
|
anvil_cost |
Non Negative Int | The base cost to apply this enchantment through an anvil. | |
weight |
Integer (1-1024) | The weight of this enchantment within the enchanting table. |
Example JSON
{
"anvil_cost": 8,
"description": {
"translate": "enchantment.enchiridion.ashes_curse"
},
"effects": {
"enchiridion:post_block_drop": [
{
"effect": {
"type": "minecraft:ignite",
"duration": 5.0
}
}
],
"enchiridion:post_entity_drop": [
{
"effect": {
"type": "minecraft:ignite",
"duration": 5.0
}
}
]
},
"max_cost": {
"base": 50,
"per_level_above_first": 0
},
"max_level": 1,
"min_cost": {
"base": 25,
"per_level_above_first": 0
},
"slots": [
"mainhand"
],
"supported_items": "#enchiridion:enchantable/ashes",
"weight": 1
}
This is an example from my WIP mod, Enchiridion, this sets dropped items from blocks and entities on fire.
Custom Enchantment Effect components are a special DataComponentType that are stored on an item's enchantment instances, and can be called through them. This is the same system as item components, so if you've worked with them, you should understand this a little better. Typically, you should make sure your component types contain a list, so they may stack with other cases of the same effect.
There are some specific classes that you may wish to look into. These are:
- ConditionalEffect (Mojmap)/EnchantmentEffectEntry (Yarn)
- EnchantmentLocationBasedEffect
Registering an enchantment component is done through typical registry means, the below is an example of a ConditionalEffect. Make sure to check LootContextParamSets (Mojmap)/LootContextTypes (Yarn)
public static final DataComponentType<List<ConditionalEffect<PreventHungerConsumptionEffect>>> PREVENT_HUNGER_CONSUMPTION = DataComponentType.<List<ConditionalEffect<PreventHungerConsumptionEffect>>>builder()
.persistent(ConditionalEffect.codec(PreventHungerConsumptionEffect.CODEC, LootContextParamSets.ENCHANTED_ENTITY).listOf())
.build();
EnchantmentHelper has some helper methods for getting whether an entity has an enchantment and for more basic usages of enchantment effects, conditions are another story.