From 94bccc3f1d0a080a4dd29f5ef52e657b37c1a9b8 Mon Sep 17 00:00:00 2001 From: Hyperlynx Date: Sat, 12 Oct 2024 23:44:32 -0500 Subject: [PATCH] Add Enchantments page (#165) Co-authored-by: ChampionAsh5357 Co-authored-by: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> --- docs/resources/server/enchantments/builtin.md | 341 ++++++++++++++++++ docs/resources/server/enchantments/index.md | 325 +++++++++++++++++ 2 files changed, 666 insertions(+) create mode 100644 docs/resources/server/enchantments/builtin.md create mode 100644 docs/resources/server/enchantments/index.md diff --git a/docs/resources/server/enchantments/builtin.md b/docs/resources/server/enchantments/builtin.md new file mode 100644 index 000000000..dcd15a573 --- /dev/null +++ b/docs/resources/server/enchantments/builtin.md @@ -0,0 +1,341 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Built-In Enchantment Effect Components + +Vanilla Minecraft provides numerous different types of enchantment effect components for use in [enchantment] definitions. This article will explain each, including their usage and in-code definition. + +## Value Effect Components + +_See also [Value Effect Components] on the Minecraft Wiki_ + +Value effect components are used for enchantments that alter a numerical value somewhere in the game, and are implemented by the class `EnchantmentValueEffect`. If a value is altered by more than one value effect component (for example, by multiple enchantments), all of their effects will apply. + +Value effect components can be set to use any of these operations on their given values: +- `minecraft:set`: Overwrites the given level-based value. +- `minecraft:add`: Adds the specified level-based value to the old one. +- `minecraft:multiply`: Multiplies the specified level-based factor by the old one. +- `minecraft:remove_binomial`: Polls a given (level-based) chance using a binomial distibution. If it works, subtracts 1 from the value. Note that many values are effectively flags, being fully on at 1 and fully off at 0. +- `minecraft:all_of`: Accepts a list of other value effects and applies them in the stated sequence. + +The Sharpness enchantment uses `minecraft:damage`, a value effect component, as follows to achieve its effect: + + + + +```json5 +"effects": { + // The type of this effect component is "minecraft:damage". + // This means that the effect will modify weapon damage. + // See below for a list of more effect component types. + "minecraft:damage": [ + { + // A value effect that should be applied. + // In this case, since there's only one, this value effect is just named "effect". + "effect": { + // The type of value effect to use. In this case, it is "minecraft:add", so the value (given below) will be added + // to the weapon damage value. + "type": "minecraft:add", + + // The value block. In this case, the value is a LevelBasedValue that starts at 1 and increases by 0.5 every enchantment level. + "value": { + "type": "minecraft:linear", + "base": 1.0, + "per_level_above_first": 0.5 + } + } + } + ] +} +``` + + + + +```java +// Passed into 'effects' in an Enchantment during data generation +// See the Data Generation section of the Enchantments entry to learn more +DataComponentMap.builder().set( + // Selects the "minecraft:damage" component. + EnchantmentEffectComponents.DAMAGE, + + // Constructs a list of one conditional AddValue without any requirements. + List.of(new ConditionalEffect<>( + new AddValue(LevelBasedValue.perLevel(1.0F, 0.5F)), + Optional.empty())) +).build() +``` + + + + +The object within the `value` block is a [LevelBasedValue], which can be used to have a value effect component that changes the intensity of its effect by level. + +The `EnchantmentValueEffect#process` method can be used to adjust values based on the provided numerical operations, like so: + +```java +// `valueEffect` is an EnchantmentValueEffect instance. +// `enchantLevel` is an integer representing the level of the enchantment +float baseValue = 1.0; +float modifiedValue = valueEffect.process(enchantLevel, server.random, baseValue); +``` + +### Vanilla Enchantment Value Effect Component Types + +#### Defined as `DataComponentType` + +- `minecraft:crossbow_charge_time`: Modifies the charge-up time of this crossbow in seconds. Used by Quick Charge. +- `minecraft:trident_spin_attack_strength`: Modifies the 'strength' of the spin attack of a trident (see `TridentItem#releaseUsing`). Used by Riptide. + +#### Defined as `DataComponentType>>` + +Armor related: +- `minecraft:armor_effectiveness`: Determines effectiveness of armor against this weapon on a scale of 0 (no protection) to 1 (normal protection). Used by Breach. +- `minecraft:damage_protection`: Each "point" of damage reduction reduces damage taken while wielding this item by 4%, to a maximum reduction of 80%. Used by Blast Protection, Feather Falling, Fire Protection, Protection, and Projectile Protection. + +Attack related: +- `minecraft:damage`: Modifies attack damage with this weapon. Used by Sharpness, Impaling, Bane of Arthropods, Power, and Smite. +- `minecraft:smash_damage_per_fallen_block`: Adds damage per block fallen to a mace. Used by Density. +- `minecraft:knockback`: Modifies the amount of knockback caused while wielding this weapon, measured in game units. Used by Knockback and Punch. +- `minecraft:mob_experience`: Modifies the amount of experience for killing a mob. Unused. + +Durability related: +- `minecraft:item_damage`: Modifies the durability damage taken by the item. Values below 1 act as a chance that the item takes damage. Used by Unbreaking. +- `minecraft:repair_with_xp`: Causes the item to repair itself using XP gain, and determines how effective this is. Used by Mending. + +Projectile related: +- `minecraft:ammo_use`: Modifies the amount of ammo used when firing a bow or crossbow. The value is clamped to an integer, so values below 1 will result in 0 ammo use. Used by Infinity. +- `minecraft:projectile_piercing`: Modifies the number of entities pierced by a projectile from this weapon. Used by Piercing. +- `minecraft:projectile_count`: Modifies the number of projectiles spawned when shooting this bow. Used by Multishot. +- `minecraft:projectile_spread`: Modifies the maximum spread of projectiles in degrees from the direction they were fired. Used by Multishot. +- `minecraft:trident_return_acceleration`: Causes the trident to return to its owner, and modifies the acceleration applied to this trident while doing so. Used by Loyalty. + +Other: +- `minecraft:block_experience`: Modifies the amount of XP from breaking a block. Used by Silk Touch. +- `minecraft:fishing_time_reduction`: Reduces the time it takes for the bobber to sink while fishing with this rod by the given number of seconds. Used by Lure. +- `minecraft:fishing_luck_bonus`: Modifies the amount of [luck] used in the fishing loot table. Used by Luck of the Sea. + +#### Defined as `DataComponentType>>` + +- `minecraft:equipment_drops`: Modifies the chance of equipment dropping from an entity killed by this weapon. Used by Looting. + +## Location Based Effect Components + +_See also: [Location Based Effect Components] on the Minecraft Wiki_ + +Location based effect components are components that implement `EnchantmentLocationBasedEffect`. These components define actions to take that need to know where in the level the wielder of the enchantment is. They operate using two major methods: `EnchantmentEntityEffect#onChangedBlock`, which is called when the enchanted item is equipped and when the wielder changes their `BlockPos`, and `onDeactivate`, which is called when the enchanted item is removed. + +Here is an example which uses the `minecraft:attributes` location based effect component type to change the wielder's entity scale: + + + + +```json5 +// The type is "minecraft:attributes" (described below). +// In a nutshell, this applies an attribute modifier. +"minecraft:attributes": [ + { + // This "amount" block is a LevelBasedValue. + "amount": { + "type": "minecraft:linear", + "base": 1, + "per_level_above_first": 1 + }, + + // Which attribute to modify. In this case, modifies "minecraft:scale" + "attribute": "minecraft:generic.scale", + // The unique identifier for this attribute modifier. Should not overlap with others, but doesn't need to be registered. + "id": "examplemod:enchantment.size_change", + // What operation to use on the attribute. Can be "add_value", "add_multiplied_base", or "add_multiplied_total". + "operation": "add_value" + } +], +``` + + + + +```java +// Passed into the effects of an Enchantment during data generation +DataComponentMap.builder().set( + // Specifies the "minecraft:attributes" component type. + EnchantmentEffectComponents.ATTRIBUTES, + + // This component takes a list of these EnchantmentAttributeEffect objects. + List.of(new EnchantmentAttributeEffect( + ResourceLocation.fromNamespaceAndPath("examplemod", "enchantment.size_change"), + Attributes.SCALE, + LevelBasedValue.perLevel(1F, 1F), + AttributeModifier.Operation.ADD_VALUE + )) +).build() +``` + + + + + +Vanilla adds the following location based events: + +- `minecraft:all_of`: Runs a list of entity effects in sequence. +- `minecraft:apply_mob_effect`: Applies a [mob effect] to the affected mob. +- `minecraft:attribute`: Applies an [attribute modifier] to the wielder of the enchantment. +- `minecraft:damage_entity`: Does damage to the affected entity. This stacks with attack damage if in an attacking context. +- `minecraft:damage_item`: Damages this item's durability. +- `minecraft:explode`: Summons an explosion. +- `minecraft:ignite`: Sets the entity on fire. +- `minecraft:play_sound`: Plays a specified sound. +- `minecraft:replace_block`: Replaces a block at a given offset. +- `minecraft:replace_disk`: Replaces a disk of blocks. +- `minecraft:run_function`: Runs a specified [datapack function]. +- `minecraft:set_block_properies`: Modifies the block state properties of the specified block. +- `minecraft:spawn_particles`: Spawns a particle. +- `minecraft:summon_entity`: Summons an entity. + +### Vanilla Location Based Effect Component Types + +#### Defined as `DataComponentType>>` + +- `minecraft:location_changed`: Runs a location based effect when the wielder's Block Position changes and when this item is equipped. Used by Frost Walker and Soul Speed. + +#### Defined as `DataComponentType>` + +- `minecraft:attributes`: Applies an attribute modifier to the wielder, and removes it when the enchanted item is no longer equipped. + +## Entity Effect Components + +_See also [Entity Effect Components] on the Minecraft Wiki._ + +Entity effect components are components that implement `EnchantmentEntityEffect`, an subtype of `EnchantmentLocationBasedEffect`. These override `EnchantmentLocationBasedEffect#onChangedBlock` to run `EnchantmentEntityEffect#apply` instead; this `apply` method is also directly invoked somewhere else in the codebase depending on the specific type of the component. This allows effects to occur without waiting for the wielder's block position to change. + +All types of location based effect component are also valid types of entity effect component, except for `minecraft:attribute`, which is registered only as a location based effect component. + +Here is an example of the JSON definition of one such component from the Fire Aspect enchantment: + + + + +```json5 +// This component's type is "minecraft:post_attack" (see below). +"minecraft:post_attack": [ + { + // Decides whether the "victim" of the attack, the "attacker", or the "damaging entity" (the projectile if there is one, attacker if not) recieves the effect. + "affected": "victim", + + // Decides which enchantment entity effect to apply. + "effect": { + // The type of this effect is "minecraft:ignite". + "type": "minecraft:ignite", + // "minecraft:ignite" requires a LevelBasedValue as a duration for how long the entity will be ignited. + "duration": { + "type": "minecraft:linear", + "base": 4.0, + "per_level_above_first": 4.0 + } + }, + + // Decides who (the "victim", "attacker", or "damaging entity") must have the enchantment for it to take effect. + "enchanted": "attacker", + + // An optional predicate which controls whether the effect applies. + "requirements": { + "condition": "minecraft:damage_source_properties", + "predicate": { + "is_direct": true + } + } + } +] +``` + + + + +```java +// Passed into the effects of an Enchantment during data generation +DataComponentMap.builder().set( + // Specifies the "minecraft:post_attack" component type. + EnchantmentEffectComponents.POST_ATTACK, + + // Defines the data for this component. In this case, a list of one TargetedConditionalEffect. + List.of( + new TargetedConditionalEffect<>( + + // Determines the "enchanted" field. + EnchantmentTarget.ATTACKER, + + // Determines the "affected" field. + EnchantmentTarget.VICTIM, + + // The enchantment entity effect. + new Ignite(LevelBasedValue.perLevel(4.0F, 4.0F)), + + // The "requirements" clause. + // In this case, the only optional part activated is the isDirect boolean flag. + Optional.of( + new DamageSourceCondition( + Optional.of( + new DamageSourcePredicate( + List.of(), + Optional.empty(), + Optional.empty(), + Optional.of(true) + ) + ) + ) + ) + ) + ) +).build() +``` + + + + +Here, the entity effect component is `minecraft:post_attack`. Its effect is `minecraft:ignite`, which is implemented by the `Ignite` record. This record's implementation of `EnchantmentEntityEffect#apply` sets the target entity on fire. + +### Vanilla Enchantment Entity Effect Component Types + +#### Defined as `DataComponentType>>` + +- `minecraft:hit_block`: Runs an entity effect when an entity (for example, a projectile) hits a block. Used by Channeling. +- `minecraft:tick`: Runs an entity effect each tick. Used by Soul Speed. +- `minecraft:projectile_spawned`: Runs an entity effect after a projectile entity has been spawned from a bow or crossbow. Used by Flame. + +#### Defined as `DataComponentType>>` + +- `minecraft:post_attack`: Runs an entity effect after an attack damages an entity. Used by Bane of Arthropods, Channeling, Fire Aspect, Thorns, and Wind Burst. + +For more detail on each of these, please look at the [relevant minecraft wiki page]. + +## Other Vanilla Enchantment Component Types + +#### Defined as `DataComponentType>>` + +- `minecraft:damage_immunity`: Applies immunity to a specified damage type. Used by Frost Walker. + +#### Defined as `DataComponentType` + +- `minecraft:prevent_equipment_drop`: Prevents this item from being dropped by a player when dying. Used by Curse of Vanishing. +- `minecraft:prevent_armor_change`: Prevents this item from being unequipped from an armor slot. Used by Curse of Binding. + +#### Defined as `DataComponentType>` + +- `minecraft:crossbow_charge_sounds`: Determines the sound events that occur when charging a crossbow. Each entry represents one level of the enchantment. + +#### Defined as `DataComponentType>>` + +- `minecraft:trident_sound`: Determines the sound events that occur when using a trident. Each entry represents one level of the enchantment. + +[enchantment]: index.md +[Value Effect Components]: https://minecraft.wiki/w/Enchantment_definition#Components_with_value_effects +[Entity Effect Components]: https://minecraft.wiki/w/Enchantment_definition#Components_with_entity_effects +[Location Based Effect Components]: https://minecraft.wiki/w/Enchantment_definition#location_changed +[text component]: /docs/resources/client/i18n.md +[LevelBasedValue]: /docs/resources/server/loottables/#number-provider +[Attribute Effect Component]: https://minecraft.wiki/w/Enchantment_definition#Attribute_effects +[datapack function]: https://minecraft.wiki/w/Function_(Java_Edition) +[luck]: https://minecraft.wiki/w/Luck +[mob effect]: /docs/items/mobeffects/ +[attribute modifier]: https://minecraft.wiki/w/Attribute#Modifiers +[relevant minecraft wiki page]: https://minecraft.wiki/w/Enchantment_definition#Components_with_entity_effects \ No newline at end of file diff --git a/docs/resources/server/enchantments/index.md b/docs/resources/server/enchantments/index.md new file mode 100644 index 000000000..3a9286a6e --- /dev/null +++ b/docs/resources/server/enchantments/index.md @@ -0,0 +1,325 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Enchantments + +Enchantments are special effects that can be applied to tools and other items. As of 1.21, enchantments are stored on items as [Data Components], are defined in JSON, and are comprised of so-called enchantment effect components. During the game, the enchantments on a particular item are contained within the `DataComponentTypes.ENCHANTMENT` component, in an `ItemEnchantment` instance. + +A new enchantment can be added by creating a JSON file in your namespace's `enchantment` datapack subfolder. For example, to create an enchantment called `examplemod:example_enchant`, one would create a file `data/examplemod/enchantment/example_enchantment.json`. + +## Enchantment JSON Format + +```json5 +{ + // The text component that will be used as the in-game name of the enchantment. + // Can be a translation key or a literal string. + // Remember to translate this in your lang file if you use a translation key! + "description": { + "translate": "enchantment.examplemod.enchant_name" + }, + + // Which items this enchantment can be applied to. + // Can be either an item id, such as "minecraft:trident", + // or a list of item ids, such as ["examplemod:red_sword", "examplemod:blue_sword"] + // or an item tag, such as "#examplemod:enchantable/enchant_name". + // Note that this doesn't cause the enchantment to appear for these items in the enchanting table. + "supported_items": "#examplemod:enchantable/enchant_name", + + // (Optional) Which items this enchantment appears for in the enchanting table. + // Can be an item, list of items, or item tag. + // If left unspecified, this is the same as `supported_items`. + "primary_items": [ + "examplemod:item_a", + "examplemod:item_b" + ], + + // (Optional) Which enchantments are incompatible with this one. + // Can be an enchantment id, such as "minecraft:sharpness", + // or a list of enchantment ids, such as ["minecraft:sharpness", "minecraft:fire_aspect"], + // or enchantment tag, such as "#examplemod:exclusive_to_enchant_name". + // Incompatible enchantments will not be added to the same item by vanilla mechanics. + "exclusive_set": "#examplemod:exclusive_to_enchant_name", + + // The likelihood that this enchantment will appear in the Enchanting Table. + // Bounded by [1, 1024]. + "weight": 6, + + // The maximum level this enchantment is allowed to reach. + // Bounded by [1, 255]. + "max_level": 3, + + // The maximum cost of this enchantment, measured in "enchanting power". + // This corresponds to, but is not equivalent to, the threshold in levels the player needs to meet to bestow this enchantment. + // See below for details. + // The actual cost will be between this and the min_cost. + "max_cost": { + "base": 45, + "per_level_above_first": 9 + }, + + // Specifies the minimum cost of this enchantment; otherwise as above. + "min_cost": { + "base": 2, + "per_level_above_first": 8 + }, + + // The cost that this enchantment adds to repairing an item in an anvil in levels. The cost is multiplied by enchantment level. + // If an item has a DataComponentTypes.STORED_ENCHANTMENTS component, the cost is halved. In vanilla, this only applies to enchanted books. + // Bounded by [1, inf). + "anvil_cost": 2, + + // (Optional) A list of slot groups this enchantment provides effects in. + // A slot group is defined as one of the possible values of the EquipmentSlotGroup enum. + // In vanilla, these are: `any`, `hand`, `mainhand`, `offhand`, `armor`, `feet`, `legs`, `chest`, `head`, and `body`. + "slots": [ + "mainhand" + ], + + // The effects that this enchantment provides as a map of enchantment effect components (read on). + "effects": { + "examplemod:custom_effect": [ + { + "effect": { + "type": "minecraft:add", + "value": { + "type": "minecraft:linear", + "base": 1, + "per_level_above_first": 1 + } + } + } + ] + } +} +``` + +### Enchantment Costs and Levels + +The `max_cost` and `min_cost` fields specify boundaries for how much enchanting power is needed to create this enchantment. There is a somewhat convoluted procedure to actually make use of these values, however. + +First, the table takes into account the return value of `IBlockExtension#getEnchantPowerBonus()` for the surrounding blocks. From this, it calls `EnchantmentHelper#getEnchantmentCost` to derive a 'base level' for each slot. This level is shown in-game as the green numbers besides the enchantments in the menu. For each enchantment, the base level is modified twice by a random value derived from the item's enchantability (its return value from `IItemExtension#getEnchantmentValue()`), like so: + +`(Modified Level) = (Base Level) + random.nextInt(e / 4 + 1) + random.nextInt(e / 4 + 1)`, where `e` is the enchantability score. + +This modified level is adjusted up or down by a random 15%, and then is finally used to choose an enchantment. This level must fall within your enchantment's cost bounds in order for it to be chosen. + +In practical terms, this means that the cost values in your enchantment definition might be above 30, sometimes far above. For example, with an enchantability 10 item, the table could produce enchantments up to 1.15 * (30 + 2 * (10 / 4) + 1) = 40 cost. + +## Enchantment Effect Components + +Enchantment effect components are specially-registered [Data Components] that determine how an enchantment functions. The type of the component defines its effect, while the data it contains is used to inform or modify that effect. For instance, the `minecraft:damage` component modifies the damage that a weapon deals by an amount determined by its data. + +Vanilla defines various [built-in enchantment effect components], which are used to implement all vanilla enchantments. + +### Custom Enchantment Effect Components + +The logic of applying a custom enchantment effect component must be entirely implemented by its creator. First, you should define a class or record to hold the information you need to implement a given effect. For example, let's make an example record class `Increment`: + +```java +// Define an example data-bearing record. +public record Increment(int value) { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + Codec.INT.fieldOf("value").forGetter(Increment::value) + ).apply(instance, Increment::new) + ); + + public int add(int x) { + return value() + x; + } +} +``` + +Enchantment effect component types must be [registered] to `BuiltInRegistries.ENCHANTMENT_EFFECT_COMPONENT_TYPE`, which takes a `DataComponentType`. For example, you could register an enchantment effect component that can store an `Increment` object as follows: + +```java +// In some registration class +public static final DeferredRegister> ENCHANTMENT_COMPONENT_TYPES = DeferredRegister.create(BuiltInRegistries.ENCHANTMENT_EFFECT_COMPONENT_TYPE, "examplemod"); + +public static final DeferredHolder, DataComponentType>> INCREMENT = + ENCHANTMENT_COMPONENT_TYPES.register("increment", + () -> DataComponentType.builder() + .persistent(Increment.CODEC) + .build()); +``` + +Now, we can implement some game logic that makes use of this component to alter an integer value: + +```java +// Somewhere in game logic where an `itemStack` is available. +// `INCREMENT` is the enchantment component type holder defined above. +// `value` is an integer. +AtomicInteger atomicValue = new AtomicInteger(value); + +EnchantmentHelper.runIterationOnItem(stack, (enchantmentHolder, enchantLevel) -> { + // Acquire the Increment instance from the enchantment holder (or null if this is a different enchantment) + Increment increment = enchantmentHolder.value().effects().get(INCREMENT.get()); + + // If this enchant has an Increment component, use it. + if(increment != null){ + atomicValue.set(increment.add(atomicValue.get())); + } +}); + +int modifiedValue = atomicValue.get(); +// Use the now-modified value elsewhere in your game logic. +``` + +First, we invoke one of the overloads of `EnchantmentHelper#runIterationOnItem`. This function accepts an `EnchantmentHelper.EnchantmentVisitor`, which is a functional interface that accepts an enchantment and its level, and is invoked on all of the enchantments that the given itemstack has (essentially a `BiConsumer`). + +To actually perform the adjustment, use the provided `Increment#add` method. Since this is inside of a lambda expression, we need to use a type that can be updated atomically, such as `AtomicInteger`, to modify this value. This also permits multiple `INCREMENT` components to run on the same item and stack their effects, like what happens in vanilla. + +### `ConditionalEffect` +Wrapping the type in `ConditionalEffect` allows the enchantment effect component to optionally take effect based on a given [LootContext]. + +`ConditionalEffect` provides `ConditionalEffect#matches(LootContext context)`, which returns whether the effect should be allowed to run based on its internal `Optional`, and handled serialization and deserialization of its `LootItemCondition`. + +Vanilla adds an additional helper method to further streamline the process of checking these conditions: `Enchantment#applyEffects()`. This method takes a `List>`, evaluates the conditions, and runs a `Consumer` on each `T` contained by a `ConditionalEffect` whose condition was met. Since many vanilla enchantment effect components are defined as a `List>`, these can be directly plugged into the helper method like so: + +```java +// `enchant` is an Enchantment instance. +// `lootContext` is a LootContext instance. +Enchantment.applyEffects( + enchant.getEffects(EnchantmentEffectComponents.KNOCKBACK), // Or whichever other List> you want + lootContext, + (effectData) -> // Use the effectData (in this example, an EnchantmentValueEffect) however you want. +); +``` + +Registering a custom `ConditionalEffect`-wrapped enchantment effect component type can be done as follows: + +```java +public static final DeferredHolder, DataComponentType>> CONDITIONAL_INCREMENT = + ENCHANTMENT_COMPONENT_TYPES.register("conditional_increment", + () -> DataComponentType.ConditionalEffectbuilder() + // The LootContextParamSet needed depends on what the enchantment is supposed to do. + // This might be one of ENCHANTED_DAMAGE, ENCHANTED_ITEM, ENCHANTED_LOCATION, ENCHANTED_ENTITY, or HIT_BLOCK + // since all of these bring the enchantment level into context (along with whatever other information is indicated). + .persistent(ConditionalEffect.codec(Increment.CODEC, LootContextParamSets.ENCHANTED_DAMAGE)) + .build()); +``` +The parameters to `ConditionalEffect.codec` are the codec for the generic `ConditionalEffect`, followed by some `LootContextParamSets` entry. + +## Enchantment Data Generation + +Enchantment JSON files can be created automatically using the [data generation] system by passing a `RegistrySetBuilder` into `DatapackBuiltInEntriesProvider`. The JSON will be placed in `/src/generated/data//enchantment/.json`. + +For more information on how `RegistrySetBuilder` and `DatapackBuiltinEntriesProvider` work, please see the article on [Data Generation for Datapack Registries]. + + + + +```java + +// This RegistrySetBuilder should be passed into a DatapackBuiltinEntriesProvider in your GatherDataEvent handler. +RegistrySetBuilder BUILDER = new RegistrySetBuilder(); +BUILDER.add( + Registries.ENCHANTMENT, + bootstrap -> bootstrap.register( + // Define the ResourceKey for our enchantment. + ResourceKey.create( + Registries.ENCHANTMENT, + ResourceLocation.fromNamespaceAndPath("examplemod", "example_enchantment") + ), + new Enchantment( + // The text Component that specifies the enchantment's name. + Component.literal("Example Enchantment"), + + // Specify the enchantment definition of for our enchantment. + new Enchantment.EnchantmentDefinition( + // A HolderSet of Items that the enchantment will be compatible with. + HolderSet.direct(...), + + // An Optional of items that the enchantment considers "primary". + Optional.empty(), + + // The weight of the enchantment. + 30, + + // The maximum level this enchantment can be. + 3, + + // The minimum cost of the enchantment. The first parameter is base cost, the second is cost per level. + new Enchantment.Cost(3, 1), + + // The maximum cost of the enchantment. As above. + new Enchantment.Cost(4, 2), + + // The anvil cost of the enchantment. + 2, + + // A list of EquipmentSlotGroups that this enchantment has effects in. + List.of(EquipmentSlotGroup.ANY) + ), + // A HolderSet of incompatible other enchantments. + HolderSet.empty(), + + // A DataComponentMap of the enchantment effect components associated with this enchantment and their values. + DataComponentMap.builder() + .set(MY_ENCHANTMENT_EFFECT_COMPONENT_TYPE, new ExampleData()) + .build() + ) + ) +); + +``` + + + + + +```json5 +// For more detail on each entry, please check the section above on the enchantment JSON format. +{ + // The anvil cost of the enchantment. + "anvil_cost": 2, + + // The text Component that specifies the enchantment's name. + "description": "Example Enchantment", + + // A map of the effect components associated with this enchantment and their values. + "effects": { + + }, + + // The maximum cost of the enchantment. + "max_cost": { + "base": 4, + "per_level_above_first": 2 + }, + + // The maximum level this enchantment can be. + "max_level": 3, + + // The minimum cost of the enchantment. + "min_cost": { + "base": 3, + "per_level_above_first": 1 + }, + + // A list of EquipmentSlotGroup aliases that this enchantment has effects in. + "slots": [ + "any" + ], + + // The set of items that this enchantment can be applied to using an anvil. + "supported_items": , + + // The weight of this enchantment. + "weight": 30 +} +``` + + + + +[Data Components]: /docs/items/datacomponents +[Codec]: /docs/datastorage/codecs +[Enchantment definition Minecraft wiki page]: https://minecraft.wiki/w/Enchantment_definition +[registered]: /docs/concepts/registries +[Predicate]: https://minecraft.wiki/w/Predicate +[data generation]: /docs/resources/#data-generation +[Data Generation for Datapack Registries]: https://docs.neoforged.net/docs/concepts/registries/#data-generation-for-datapack-registries +[relevant minecraft wiki page]: https://minecraft.wiki/w/Enchantment_definition#Entity_effects +[built-in enchantment effect components]: builtin.md +[LootContext]: /docs/resources/server/loottables/#loot-context \ No newline at end of file