Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.json to 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 /reload because 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:

  • description is 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 a translate key (so the name can be localized) with a fallback string 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_items is the set of items this enchantment can be applied to using an anvil or the /enchant command. 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 of supported_items. If you leave it out, it defaults to being the same as supported_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 in supported_items can get it from a book on an anvil but never from the table.

  • weight is a value from 1 to 1024 that controls how likely this enchantment is to be offered when enchanting. The probability is weight / total_weight, where total_weight is the sum of the weights of every enchantment available for that item. Rare vanilla enchantments use low weights; common ones use high weights. Our 5 makes Frostbite uncommon.

  • max_level is the highest level the enchantment can reach, from 1 to 255. Ours caps at 3 (you’ll see “Frostbite III” as the strongest version).

  • min_cost and max_cost together 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, and per_level_above_first, how much to add for each level beyond the first. So our min_cost is 10 at level I, 18 at level II, 26 at level III. (The table modifies this range further with some bookshelf math, but base and per_level_above_first are the numbers you control.)

  • anvil_cost is 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.

  • slots is the list of equipment slots the enchantment actually works in. Each entry is one of any, hand, mainhand, offhand, armor, feet, legs, chest, head, body, or saddle. A weapon enchantment like ours only does anything in mainhand. An armor enchantment would use a slot like chest or the catch-all armor; a boots enchantment, feet.

  • exclusive_set lists 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.

  • effects is the heart of the file: the block that says what the enchantment does. That’s the whole next section.

Try It! Change max_level to 1 and weight to 30, and reboot the world. Frostbite is now a common, single-level enchantment, much more likely to show up at a table. Tweaking weight, 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:

  1. A value effect changes a number, like adding to the damage dealt, or to mining speed. These use the small type-based shapes minecraft:add, minecraft:set, minecraft:multiply, minecraft:remove_binomial, and minecraft:all_of. (Sharpness, under the hood, is a value effect that adds to damage.)

  2. 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.

  3. 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_apply is the status effect (or a tag of effects) to apply. We chose minecraft:slowness.
  • min_duration / max_duration are 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_amplifier are 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 of attacker, victim, or damaging_entity. We used attacker: you, the one swinging the enchanted sword.
  • affected — which entity the effect lands on. Also one of attacker, victim, or damaging_entity. We used victim: 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 effects block can be a level-based value instead of a plain number, so a higher enchantment level does more. The simplest form is minecraft:linear, defined as base + per_level_above_first * (level - 1). If we wanted Frostbite’s slow to last longer at higher levels, we’d replace "max_duration": 3.0 with:

"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 a minecraft:lookup form that lists a value per level, but linear covers 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_attack wrapper (enchanted: attacker, affected: victim) and swap the inner effect for the minecraft:ignite shape: {"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.json but 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 out slots or supported_items doesn’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.

  1. Write the definition. Create data/mypack/enchantment/frostbite.json from Walkthrough A, effects block and all. Save it.

  2. 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 optionally tooltip_order.json.

  3. Reboot the world. Save and quit to the title screen, then re-open the world. This is the step everyone forgets, and /reload will not pick up your enchantment.

  4. Apply it and test. The fastest way to put your enchantment on a held sword is the /enchant command, which “adds an enchantment to a player’s selected item.” Hold a sword and run, in chat:

    /enchant @s mypack:frostbite 2
    

    That 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 .mcfunction file with the / dropped, exactly as in earlier chapters.)

  5. 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 (its weight is 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:linear level-based value from Walkthrough B so higher levels slow for longer.
  • Change the payload. Swap apply_mob_effect for minecraft:ignite (“Searing Edge”) or, once you’ve read Chapter 36 on damage types, minecraft:damage_entity for an enchantment that deals bonus damage of a type you define.
  • Armor instead of weapon. Make a defensive enchantment: change supported_items to an armor tag, set slots to ["chest"] or ["armor"], and use a post_attack effect where the enchanted entity is the victim and the affected is the attacker, 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; /reload never 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_table tag. Without that membership the table will never offer it, no matter how the definition reads. Second, its primary_items (or supported_items, if you left primary_items out) 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 effect type, or an effect component whose inner effect object is malformed will make the game reject the file. Check the game log right after the world loads for the error, and compare your effects block 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 function enchant_with_levels you 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 on enchant_with_levels in a loot table and let it handle the selection for you.