Chapter 35 — Data-Driven Enchantments
What You’ll Build
Welcome to Part X. From here on the chapters are à la carte: each one opens a self-contained system you can pick up when a project needs it, and they all assume you’ve worked through Parts I through VIII. This first one answers a question every Minecraft player eventually asks: can I make my own enchantment? The answer, in modern Minecraft, is yes, and you make one the same way you’ve made everything else in this book, by writing a JSON file.
By the end of this chapter you will have:
- A brand-new enchantment called Frostbite (a file at
data/mypack/enchantment/frostbite.json) that slows down any mob your enchanted weapon hits. - A set of small enchantment tag files that tell the game your enchantment exists in the world: which items can wear it, whether the enchanting table can offer it, and what it conflicts with.
- A modified vanilla enchantment: you’ll override Minecraft’s own
sharpness.jsonto change how it behaves, without touching a single line of the game’s code.
And you’ll learn one rule that trips up almost everyone the first time: enchantments do not
reload with /reload. They need a world reboot, and we’ll explain exactly why.
mypack/
data/
mypack/
enchantment/
frostbite.json (the new enchantment itself)
tags/
enchantment/
in_enchanting_table.json (lets the table offer Frostbite)
tooltip_order.json (where it sits in the tooltip — optional)
exclusive_set/
frostbite_group.json (what Frostbite conflicts with)
minecraft/
enchantment/
sharpness.json (our override of the vanilla enchantment)
Concepts
An enchantment is a file
Back in Chapter 7 you learned the big idea of this whole book: vanilla Minecraft is itself a data
pack, and almost everything in the game is defined by data files you’re allowed to replace. An
enchantment definition is one of those files. Put plainly: enchantments are stored as JSON
files within a data pack in the path data/<namespace>/enchantment.
So Sharpness, Mending, Protection (every enchantment you’ve ever used) is a JSON file sitting
inside Minecraft’s own minecraft namespace. To make a new one, you drop a file into your
namespace’s enchantment/ folder. To change an existing one, you put a file with the same name in
the minecraft namespace and yours wins. That’s the entire trick; the rest of this chapter is
learning what goes inside the file.
Modern Minecraft. If you’ve read older tutorials, you may have seen people insist that custom enchantments are “impossible without mods,” and that the closest you can get is faking one with scoreboards and command blocks. That was true for years. It stopped being true when enchantments became data-driven: now an enchantment is a file like a recipe or a loot table, and a plain data pack can add a real one that shows up in the enchanting table and on the item tooltip.
The reboot caveat (this one matters)
Here is the rule that will save you an hour of confusion. In Chapter 8 you learned /reload, the
command that re-reads your data pack so edits apply without leaving the world. It works on functions,
recipes, loot tables, advancements, tags: most of what you’ve built so far.
It does not work on enchantments.
The reason goes back to a distinction from Chapter 7: a dynamic registry is a registry (a master
list the game keeps) that data packs are allowed to add content to, but which the game only assembles
when a world loads. Enchantments live in a dynamic registry. So do biomes and dimensions, which
you’ll meet later. Because the list is built at world-load time, /reload, which only re-reads the
hot-reloadable files, never touches it.
To see a change to any enchantment file, you must leave the world and re-enter it (in single player: quit to the title screen or to “Save and Quit,” then open the world again). On a server, that means a full server restart. There is no command shortcut. Whenever something in this chapter “isn’t working,” the very first thing to check is whether you rebooted the world after your last edit.
Under the Hood (skippable). “Hot-reloadable” data (recipes, loot tables, functions) is re-read every
/reloadbecause the game can swap it out mid-game safely. Dynamic-registry data (enchantments, biomes, dimensions, damage types) helps define the shape of the world itself, so the game freezes it at load time for consistency and only rebuilds it on a fresh load. You don’t need to remember the mechanism — just the rule: dynamic registry → reboot, not/reload.
Walkthrough A — The anatomy of an enchantment definition
Let’s read a complete enchantment file top to bottom, then build our own. Every field below is named
exactly as the Enchantment definition page on the wiki names it. Here is Frostbite, our weapon
enchantment that slows whatever it hits. Don’t worry about the effects block yet; we’ll take that
apart in Walkthrough B. Read the fields above it first.
data/mypack/enchantment/frostbite.json
{
"description": {
"translate": "enchantment.mypack.frostbite",
"fallback": "Frostbite"
},
"supported_items": "#minecraft:enchantable/sharp_weapon",
"primary_items": "#minecraft:enchantable/sharp_weapon",
"weight": 5,
"max_level": 3,
"min_cost": {
"base": 10,
"per_level_above_first": 8
},
"max_cost": {
"base": 40,
"per_level_above_first": 8
},
"anvil_cost": 4,
"slots": [
"mainhand"
],
"exclusive_set": "#mypack:exclusive_set/frostbite_group",
"effects": {
"minecraft:post_attack": [
{
"enchanted": "attacker",
"affected": "victim",
"effect": {
"type": "minecraft:apply_mob_effect",
"to_apply": "minecraft:slowness",
"min_duration": 1.0,
"max_duration": 3.0,
"min_amplifier": 0.0,
"max_amplifier": 1.0
}
}
]
}
}
That’s the whole file. Now the fields, in order:
-
descriptionis a text component (the same kind of styled-text object you built in Chapter 5) that’s used to display the enchantment’s name on items. Here we use atranslatekey (so the name can be localized) with afallbackstring so it reads “Frostbite” even before you add a language file. A plain"description": "Frostbite"works too if you don’t care about translation. -
supported_itemsis the set of items this enchantment can be applied to using an anvil or the/enchantcommand. It’s written as a single item, a list of items, or (most usefully) an item tag with a leading#, exactly like the tags you learned in Chapter 14. We used#minecraft:enchantable/sharp_weapon, the built-in tag standing for “all swords and axes” (it’s the same tag vanilla Sharpness uses), so Frostbite goes on any of them without us listing items one by one. -
primary_items(optional) is the set of items the enchantment appears on in an enchanting table, and it must be a subset ofsupported_items. If you leave it out, it defaults to being the same assupported_items. This is the file-level version of the “primary vs secondary items” idea from vanilla: primary items can get the enchantment at the table; items that are only insupported_itemscan get it from a book on an anvil but never from the table. -
weightis a value from 1 to 1024 that controls how likely this enchantment is to be offered when enchanting. The probability isweight / total_weight, wheretotal_weightis the sum of the weights of every enchantment available for that item. Rare vanilla enchantments use low weights; common ones use high weights. Our5makes Frostbite uncommon. -
max_levelis the highest level the enchantment can reach, from 1 to 255. Ours caps at3(you’ll see “Frostbite III” as the strongest version). -
min_costandmax_costtogether set the cost range in levels the enchanting table uses when deciding whether to offer this enchantment. Each is a small object with two fields:base, the cost for a level-I enchantment, andper_level_above_first, how much to add for each level beyond the first. So ourmin_costis 10 at level I, 18 at level II, 26 at level III. (The table modifies this range further with some bookshelf math, butbaseandper_level_above_firstare the numbers you control.) -
anvil_costis the base experience-level cost of applying this enchantment with an anvil. It’s halved when you apply it from a book, and multiplied by the enchantment’s level. -
slotsis the list of equipment slots the enchantment actually works in. Each entry is one ofany,hand,mainhand,offhand,armor,feet,legs,chest,head,body, orsaddle. A weapon enchantment like ours only does anything inmainhand. An armor enchantment would use a slot likechestor the catch-allarmor; a boots enchantment,feet. -
exclusive_setlists enchantments that are incompatible with this one: the file-level version of vanilla’s conflicts (you can’t put Sharpness and Smite on the same sword). It’s an enchantment, a list of enchantments, or an enchantment tag, and defaults to an empty list (no conflicts) if you omit it. We pointed ours at a tag,#mypack:exclusive_set/frostbite_group, which we’ll create in Walkthrough C. -
effectsis the heart of the file: the block that says what the enchantment does. That’s the whole next section.
Try It! Change
max_levelto1andweightto30, and reboot the world. Frostbite is now a common, single-level enchantment, much more likely to show up at a table. Tweakingweight,max_level, and the cost range is how vanilla makes some enchantments feel rare and others routine, and you have exactly the same dials.
Walkthrough B — The effects block: what an enchantment does
Every field so far described where the enchantment lives and how you obtain it. The effects
block describes what happens when it’s equipped. This is where data-driven enchantments do the most,
and it’s worth going slowly.
The effects field holds effect components, and it controls what the enchantment does.
An effect component is one entry inside the effects block. Its key is the kind of moment the
effect hooks into: for example minecraft:post_attack (right after you hit something),
minecraft:damage_immunity (deciding whether you take damage), or minecraft:location_changed (when
the wearer moves). The value attached to that key describes what to do at that moment. Our Frostbite
used minecraft:post_attack, so it fires every time the enchanted weapon lands a hit.
Inside an effect component, the action you take is itself one of three families:
-
A value effect changes a number, like adding to the damage dealt, or to mining speed. These use the small
type-based shapesminecraft:add,minecraft:set,minecraft:multiply,minecraft:remove_binomial, andminecraft:all_of. (Sharpness, under the hood, is a value effect that adds to damage.) -
An entity effect does something to a creature: applies a status effect, deals damage, sets it on fire, spawns particles. This is the family Frostbite uses.
-
A location-based effect happens at a place. Frost Walker freezing water beneath you is the classic example.
Frostbite’s effect is an entity effect of type minecraft:apply_mob_effect, which applies a
status effect to the affected mob. Look back at our file and read the inner object:
"effect": {
"type": "minecraft:apply_mob_effect",
"to_apply": "minecraft:slowness",
"min_duration": 1.0,
"max_duration": 3.0,
"min_amplifier": 0.0,
"max_amplifier": 1.0
}
Each field is named exactly as the apply_mob_effect entry names it:
to_applyis the status effect (or a tag of effects) to apply. We choseminecraft:slowness.min_duration/max_durationare the shortest and longest possible duration in seconds. The game picks a value in that range, so Frostbite’s slow lasts somewhere from 1 to 3 seconds.min_amplifier/max_amplifierare the weakest and strongest amplifier (Slowness I has amplifier 0, Slowness II has amplifier 1). Ours ranges from 0 to 1, so it’s sometimes Slowness I, sometimes II.
Two more fields wrap the effect, and they belong to the post_attack component specifically:
enchanted— which entity must be carrying the enchantment for this to fire. One ofattacker,victim, ordamaging_entity. We usedattacker: you, the one swinging the enchanted sword.affected— which entity the effect lands on. Also one ofattacker,victim, ordamaging_entity. We usedvictim: the mob you hit. So: the attacker holds Frostbite; the victim gets the slow. Swap those two words and you’d slow yourself, a useful sanity check.
Under the Hood (skippable). Most numbers in the
effectsblock can be a level-based value instead of a plain number, so a higher enchantment level does more. The simplest form isminecraft:linear, defined asbase + per_level_above_first * (level - 1). If we wanted Frostbite’s slow to last longer at higher levels, we’d replace"max_duration": 3.0with:"max_duration": { "type": "minecraft:linear", "base": 3.0, "per_level_above_first": 1.5 }Now Frostbite I slows for up to 3 seconds, Frostbite II up to 4.5, Frostbite III up to 6. There are also
minecraft:levels_squared,minecraft:fraction,minecraft:clamped, and aminecraft:lookupform that lists a value per level, butlinearcovers most cases and a plain constant covers the rest.
The full menu of effect components and effects is large: there are value effects, many
entity effects (damage_entity, ignite, explode, spawn_particles, play_sound,
summon_entity, run_function, and more), and location-based effects. You don’t need them
memorized. You need to know the shape: an effect component keyed by a moment, holding an effect
of a known type, optionally gated by requirements (an inline predicate, the Chapter 18 kind).
When you want a behavior, open the Enchantment definition page, find the effect whose name matches
what you want, and copy its fields.
Try It! Make a “Searing Edge” enchantment that sets the victim on fire instead of slowing it. Keep the whole
post_attackwrapper (enchanted: attacker,affected: victim) and swap the innereffectfor theminecraft:igniteshape:{"type": "minecraft:ignite", "duration": 4.0}. Reboot the world and hit a pig.
Walkthrough C — Enchantment tags: telling the world your enchantment exists
You’ve written the enchantment. But by itself, a definition file is just a possible enchantment: the game knows the recipe but won’t yet hand it out at a table, and doesn’t know what it conflicts with. That wiring is done with enchantment tags.
An enchantment tag is exactly the kind of tag you learned in Chapter 14, a values list grouping
members of one registry, except the registry is enchantment. So the files live at
data/<namespace>/tags/enchantment/, and their purpose is simple: an enchantment tag is a group
of enchantments, used in loot tables, to configure exclusive enchantments, and in other gameplay
features.
The tags Minecraft itself reads (the ones with real effects) all live in the minecraft namespace,
and you add to them the same way you added to #minecraft:logs in Chapter 14: by creating a file
with the same name in your pack and listing your member, leaving replace at its default of false
so you extend the vanilla tag instead of wiping it.
1. Make Frostbite appear at the enchanting table. The in_enchanting_table tag holds the
enchantments that can be obtained from an enchanting table. Without being in it, your
enchantment can only be applied with /enchant or a command, never rolled at a table. Add yours:
data/mypack/tags/enchantment/in_enchanting_table.json
{
"values": [
"mypack:frostbite"
]
}
2. Define the exclusive set. Back in Frostbite’s definition we set
"exclusive_set": "#mypack:exclusive_set/frostbite_group". Vanilla keeps its
conflict groups as tags under exclusive_set/ (for example exclusive_set/armor,
exclusive_set/bow), each one a group whose members are mutually exclusive with each other. Let’s
make our own, putting Frostbite and the vanilla Bane of Arthropods in the same group so a sword can’t
have both:
data/mypack/tags/enchantment/exclusive_set/frostbite_group.json
{
"values": [
"mypack:frostbite",
"minecraft:bane_of_arthropods"
]
}
Note the path mirrors the tag id: a file at tags/enchantment/exclusive_set/frostbite_group.json in
the mypack namespace is the tag #mypack:exclusive_set/frostbite_group, which is exactly the id
we referenced in the definition. (Subfolders just become part of the name, the same rule you saw with
block tags in Chapter 14.)
3. (Optional) Place it in the tooltip order. The tooltip_order tag controls the order of
enchantments displayed in an item’s tooltip. If you don’t add to it, your
enchantment still shows up; it just lands at the end. To slot it deliberately, extend the vanilla
tag:
data/mypack/tags/enchantment/tooltip_order.json
{
"values": [
"mypack:frostbite"
]
}
There are many other enchantment tags, and they’re worth skimming on the Enchantment tag (Java Edition) page when you build something specific. A few you’ll reach for:
tradeable— enchantments villagers can sell.treasure/non_treasure— whether it counts as a “treasure” enchantment (table-banned, book-only, like vanilla Mending).curse— red-text, can’t-be-removed enchantments, like Curse of Binding.on_random_loot/on_mob_spawn_equipment— whether it can appear on generated loot or on mobs that spawn with gear.
Modern Minecraft. This tag system is why a plain data pack can now do what once needed a mod. The behaviors that used to be hard-coded into Minecraft’s engine (“which enchantments the table offers,” “which ones conflict,” “which villagers sell”) are all just tag memberships you’re allowed to edit. Your enchantment becomes a first-class citizen by joining the same lists the vanilla ones are in.
Walkthrough D — Modifying a vanilla enchantment
Creating a new enchantment and changing an existing one are the same move with a different file
name. Because every vanilla enchantment is a file in the minecraft namespace, you override one by
writing a file with the matching name in your pack’s minecraft namespace. Yours loads on top.
Say you think Sharpness is too weak. Sharpness lives at data/minecraft/enchantment/sharpness.json
inside the game; to override it, you write your own copy at that same path in your pack and bump its
numbers. The catch, and this matters, is that an override
replaces the whole file, not just the fields you mention. So you must supply every field
Sharpness needs, not only the ones you’re changing. Here is a complete override that gives Sharpness
a much steeper damage curve:
data/minecraft/enchantment/sharpness.json
{
"description": {
"translate": "enchantment.minecraft.sharpness"
},
"supported_items": "#minecraft:enchantable/sharp_weapon",
"primary_items": "#minecraft:enchantable/sharp_weapon",
"weight": 10,
"max_level": 5,
"min_cost": {
"base": 1,
"per_level_above_first": 11
},
"max_cost": {
"base": 21,
"per_level_above_first": 11
},
"anvil_cost": 1,
"slots": [
"mainhand"
],
"exclusive_set": "#minecraft:exclusive_set/damage",
"effects": {
"minecraft:damage": [
{
"effect": {
"type": "minecraft:add",
"value": {
"type": "minecraft:linear",
"base": 2.0,
"per_level_above_first": 2.0
}
}
}
]
}
}
The only thing we actually changed from vanilla is the damage formula in the effects block: a
value effect of type minecraft:add whose value is a minecraft:linear level-based value with
base 2.0 and per_level_above_first 2.0, so Sharpness I adds 2 damage, Sharpness V adds 10
(vanilla adds far less). Everything else is reproduced exactly so the override doesn’t accidentally
break the enchantment’s name, cost, or conflicts.
This is the cleanest illustration of the chapter’s whole idea: you didn’t mod the game, you handed it a replacement file. Reboot the world, enchant a sword with Sharpness, and check the damage.
What Went Wrong? You overrode
sharpness.jsonbut it vanished from the enchanting table entirely. Almost always this means a typo or a missing required field made the file invalid, so the game couldn’t load it. Check the game log (Chapter 10) right after the world loads; a malformed enchantment reports an error there. And remember the override is all-or-nothing: leaving outslotsorsupported_itemsdoesn’t “keep the vanilla value,” it produces a broken file.
Practice — A custom enchantment with unique behavior
Time to put it together in mypack. Build Frostbite end-to-end and prove it works in-game.
-
Write the definition. Create
data/mypack/enchantment/frostbite.jsonfrom Walkthrough A,effectsblock and all. Save it. -
Register the tags. Create the three tag files from Walkthrough C:
in_enchanting_table.json(so the table offers it),exclusive_set/frostbite_group.json(so it conflicts with Bane of Arthropods), and optionallytooltip_order.json. -
Reboot the world. Save and quit to the title screen, then re-open the world. This is the step everyone forgets, and
/reloadwill not pick up your enchantment. -
Apply it and test. The fastest way to put your enchantment on a held sword is the
/enchantcommand, which “adds an enchantment to a player’s selected item.” Hold a sword and run, in chat:/enchant @s mypack:frostbite 2That gives you Frostbite II. Now hit a mob (a pig, a zombie) and watch it slow down. (If you’d rather build it into your pack, the same command works inside a
.mcfunctionfile with the/dropped, exactly as in earlier chapters.) -
Find it at a table. Because you added Frostbite to
in_enchanting_table, enchant a fresh sword at an enchanting table a few times. With enough tries (itsweightis only 5) Frostbite will be one of the offered options: proof your enchantment is a full citizen of the game now.
Extensions (each is a small edit, then a reboot):
- Make it scale. Use the
minecraft:linearlevel-based value from Walkthrough B so higher levels slow for longer. - Change the payload. Swap
apply_mob_effectforminecraft:ignite(“Searing Edge”) or, once you’ve read Chapter 36 on damage types,minecraft:damage_entityfor an enchantment that deals bonus damage of a type you define. - Armor instead of weapon. Make a defensive enchantment: change
supported_itemsto an armor tag, setslotsto["chest"]or["armor"], and use apost_attackeffect where theenchantedentity is thevictimand theaffectedis theattacker, so being hit punishes the attacker.
What Can Go Wrong
-
You edited the file and
/reloaded, but nothing changed. This is the number-one Frostbite bug, and it isn’t a bug at all. Enchantments are a dynamic registry;/reloadnever touches them. Quit to the title screen and re-open the world (restart the server) after every enchantment or enchantment-tag edit. If a change seems ignored, this is always the first thing to rule out. -
The enchantment never appears at the enchanting table. Two common causes. First, you forgot to add it to the
in_enchanting_tabletag. Without that membership the table will never offer it, no matter how the definition reads. Second, itsprimary_items(orsupported_items, if you leftprimary_itemsout) doesn’t include the item you’re trying to enchant. The table only offers an enchantment for items in its primary set. -
The whole file fails to load (the enchantment disappears). An enchantment definition needs its required fields present and correctly shaped: a missing
supported_items, a misspelled effecttype, or an effect component whose innereffectobject is malformed will make the game reject the file. Check the game log right after the world loads for the error, and compare youreffectsblock field-by-field against the Enchantment definition page. Remember that when overriding a vanilla enchantment you must include every field, because the override replaces the entire file.
One more file type:
enchantment_provider. There’s a sibling system worth knowing the name of, even though we won’t build one here. An enchantment provider is a small file that decides which enchantments (and at what levels) get rolled onto an item in a given situation. It’s the machinery behind tools like the loot functionenchant_with_levelsyou met in Chapter 17, which enchants an item by experience level. If you ever need to author one, open the Enchantment provider page on the wiki, or copy a vanilla example and adapt the fields you find there. For most projects you won’t touch providers directly; you’ll lean onenchant_with_levelsin a loot table and let it handle the selection for you.