Skip to content

Instantly share code, notes, and snippets.

@MerchantPug
Created June 16, 2024 13:32
Show Gist options
  • Save MerchantPug/0a3ae4fe6357013e003a2d3f7989453e to your computer and use it in GitHub Desktop.
Save MerchantPug/0a3ae4fe6357013e003a2d3f7989453e to your computer and use it in GitHub Desktop.
Data Driven Enchantments, A Guide for Modders.

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.

The Basic Datapack Structure

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.

Adding Custom Enchantment Effect Components

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.

TODO: Conditions, please bug me to get this done :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment