package net.minecraft.world.item.enchantment; import com.google.common.collect.Maps; import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; import it.unimi.dsi.fastutil.objects.ObjectArraySet; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import net.minecraft.ChatFormatting; import net.minecraft.Util; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.RegistryCodecs; import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.network.chat.ComponentUtils; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.RegistryFixedCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.EnchantmentTags; import net.minecraft.util.ExtraCodecs; import net.minecraft.util.RandomSource; import net.minecraft.util.Unit; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlotGroup; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.effects.DamageImmunity; import net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect; import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect; import net.minecraft.world.item.enchantment.effects.EnchantmentLocationBasedEffect; import net.minecraft.world.item.enchantment.effects.EnchantmentValueEffect; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.phys.Vec3; import org.apache.commons.lang3.mutable.MutableFloat; public record Enchantment(Component description, Enchantment.EnchantmentDefinition definition, HolderSet exclusiveSet, DataComponentMap effects) { public static final int MAX_LEVEL = 255; public static final Codec DIRECT_CODEC = RecordCodecBuilder.create( p_344995_ -> p_344995_.group( ComponentSerialization.CODEC.fieldOf("description").forGetter(Enchantment::description), Enchantment.EnchantmentDefinition.CODEC.forGetter(Enchantment::definition), RegistryCodecs.homogeneousList(Registries.ENCHANTMENT).optionalFieldOf("exclusive_set", HolderSet.direct()).forGetter(Enchantment::exclusiveSet), EnchantmentEffectComponents.CODEC.optionalFieldOf("effects", DataComponentMap.EMPTY).forGetter(Enchantment::effects) ) .apply(p_344995_, Enchantment::new) ); public static final Codec> CODEC = RegistryFixedCodec.create(Registries.ENCHANTMENT); public static final StreamCodec> STREAM_CODEC = ByteBufCodecs.holderRegistry(Registries.ENCHANTMENT); public static Enchantment.Cost constantCost(int p_334530_) { return new Enchantment.Cost(p_334530_, 0); } public static Enchantment.Cost dynamicCost(int p_334326_, int p_335507_) { return new Enchantment.Cost(p_334326_, p_335507_); } public static Enchantment.EnchantmentDefinition definition( HolderSet p_345362_, HolderSet p_343516_, int p_328611_, int p_336009_, Enchantment.Cost p_330605_, Enchantment.Cost p_333983_, int p_327771_, EquipmentSlotGroup... p_344843_ ) { return new Enchantment.EnchantmentDefinition( p_345362_, Optional.of(p_343516_), p_328611_, p_336009_, p_330605_, p_333983_, p_327771_, List.of(p_344843_) ); } public static Enchantment.EnchantmentDefinition definition( HolderSet p_342934_, int p_329635_, int p_331888_, Enchantment.Cost p_328182_, Enchantment.Cost p_328787_, int p_333931_, EquipmentSlotGroup... p_342587_ ) { return new Enchantment.EnchantmentDefinition(p_342934_, Optional.empty(), p_329635_, p_331888_, p_328182_, p_328787_, p_333931_, List.of(p_342587_)); } public Map getSlotItems(LivingEntity p_44685_) { Map map = Maps.newEnumMap(EquipmentSlot.class); for (EquipmentSlot equipmentslot : EquipmentSlot.VALUES) { if (this.matchingSlot(equipmentslot)) { ItemStack itemstack = p_44685_.getItemBySlot(equipmentslot); if (!itemstack.isEmpty()) { map.put(equipmentslot, itemstack); } } } return map; } public HolderSet getSupportedItems() { return this.definition.supportedItems(); } public boolean matchingSlot(EquipmentSlot p_344889_) { return this.definition.slots().stream().anyMatch(p_345380_ -> p_345380_.test(p_344889_)); } public boolean isPrimaryItem(ItemStack p_334183_) { return this.isSupportedItem(p_334183_) && (this.definition.primaryItems.isEmpty() || p_334183_.is(this.definition.primaryItems.get())); } public boolean isSupportedItem(ItemStack p_343312_) { return p_343312_.is(this.definition.supportedItems); } public int getWeight() { return this.definition.weight(); } public int getAnvilCost() { return this.definition.anvilCost(); } public int getMinLevel() { return 1; } public int getMaxLevel() { return this.definition.maxLevel(); } public int getMinCost(int p_44679_) { return this.definition.minCost().calculate(p_44679_); } public int getMaxCost(int p_44691_) { return this.definition.maxCost().calculate(p_44691_); } @Override public String toString() { return "Enchantment " + this.description.getString(); } public static boolean areCompatible(Holder p_345028_, Holder p_342568_) { return !p_345028_.equals(p_342568_) && !p_345028_.value().exclusiveSet.contains(p_342568_) && !p_342568_.value().exclusiveSet.contains(p_345028_); } public static Component getFullname(Holder p_342825_, int p_44701_) { MutableComponent mutablecomponent = p_342825_.value().description.copy(); if (p_342825_.is(EnchantmentTags.CURSE)) { ComponentUtils.mergeStyles(mutablecomponent, Style.EMPTY.withColor(ChatFormatting.RED)); } else { ComponentUtils.mergeStyles(mutablecomponent, Style.EMPTY.withColor(ChatFormatting.GRAY)); } if (p_44701_ != 1 || p_342825_.value().getMaxLevel() != 1) { mutablecomponent.append(CommonComponents.SPACE).append(Component.translatable("enchantment.level." + p_44701_)); } return mutablecomponent; } public boolean canEnchant(ItemStack p_44689_) { return this.definition.supportedItems().contains(p_44689_.getItemHolder()); } public List getEffects(DataComponentType> p_344699_) { return this.effects.getOrDefault(p_344699_, List.of()); } public boolean isImmuneToDamage(ServerLevel p_344493_, int p_345313_, Entity p_342613_, DamageSource p_345401_) { LootContext lootcontext = damageContext(p_344493_, p_345313_, p_342613_, p_345401_); for (ConditionalEffect conditionaleffect : this.getEffects(EnchantmentEffectComponents.DAMAGE_IMMUNITY)) { if (conditionaleffect.matches(lootcontext)) { return true; } } return false; } public void modifyDamageProtection(ServerLevel p_344642_, int p_344297_, ItemStack p_345382_, Entity p_342229_, DamageSource p_342824_, MutableFloat p_345325_) { LootContext lootcontext = damageContext(p_344642_, p_344297_, p_342229_, p_342824_); for (ConditionalEffect conditionaleffect : this.getEffects(EnchantmentEffectComponents.DAMAGE_PROTECTION)) { if (conditionaleffect.matches(lootcontext)) { p_345325_.setValue(conditionaleffect.effect().process(p_344297_, p_342229_.getRandom(), p_345325_.floatValue())); } } } public void modifyDurabilityChange(ServerLevel p_342774_, int p_345090_, ItemStack p_343700_, MutableFloat p_343591_) { this.modifyItemFilteredCount(EnchantmentEffectComponents.ITEM_DAMAGE, p_342774_, p_345090_, p_343700_, p_343591_); } public void modifyAmmoCount(ServerLevel p_342942_, int p_342884_, ItemStack p_344742_, MutableFloat p_343607_) { this.modifyItemFilteredCount(EnchantmentEffectComponents.AMMO_USE, p_342942_, p_342884_, p_344742_, p_343607_); } public void modifyPiercingCount(ServerLevel p_342338_, int p_344838_, ItemStack p_343994_, MutableFloat p_342065_) { this.modifyItemFilteredCount(EnchantmentEffectComponents.PROJECTILE_PIERCING, p_342338_, p_344838_, p_343994_, p_342065_); } public void modifyBlockExperience(ServerLevel p_342072_, int p_343543_, ItemStack p_343319_, MutableFloat p_342766_) { this.modifyItemFilteredCount(EnchantmentEffectComponents.BLOCK_EXPERIENCE, p_342072_, p_343543_, p_343319_, p_342766_); } public void modifyMobExperience(ServerLevel p_343695_, int p_342521_, ItemStack p_344064_, Entity p_342215_, MutableFloat p_345517_) { this.modifyEntityFilteredValue(EnchantmentEffectComponents.MOB_EXPERIENCE, p_343695_, p_342521_, p_344064_, p_342215_, p_345517_); } public void modifyDurabilityToRepairFromXp(ServerLevel p_343302_, int p_343123_, ItemStack p_343007_, MutableFloat p_342327_) { this.modifyItemFilteredCount(EnchantmentEffectComponents.REPAIR_WITH_XP, p_343302_, p_343123_, p_343007_, p_342327_); } public void modifyTridentReturnToOwnerAcceleration(ServerLevel p_344014_, int p_345042_, ItemStack p_343051_, Entity p_342961_, MutableFloat p_343498_) { this.modifyEntityFilteredValue(EnchantmentEffectComponents.TRIDENT_RETURN_ACCELERATION, p_344014_, p_345042_, p_343051_, p_342961_, p_343498_); } public void modifyTridentSpinAttackStrength(RandomSource p_343013_, int p_342342_, MutableFloat p_342582_) { this.modifyUnfilteredValue(EnchantmentEffectComponents.TRIDENT_SPIN_ATTACK_STRENGTH, p_343013_, p_342342_, p_342582_); } public void modifyFishingTimeReduction(ServerLevel p_343004_, int p_344690_, ItemStack p_342235_, Entity p_344564_, MutableFloat p_345086_) { this.modifyEntityFilteredValue(EnchantmentEffectComponents.FISHING_TIME_REDUCTION, p_343004_, p_344690_, p_342235_, p_344564_, p_345086_); } public void modifyFishingLuckBonus(ServerLevel p_342216_, int p_343343_, ItemStack p_344550_, Entity p_343347_, MutableFloat p_345240_) { this.modifyEntityFilteredValue(EnchantmentEffectComponents.FISHING_LUCK_BONUS, p_342216_, p_343343_, p_344550_, p_343347_, p_345240_); } public void modifyDamage(ServerLevel p_343328_, int p_344751_, ItemStack p_342664_, Entity p_344239_, DamageSource p_345253_, MutableFloat p_344727_) { this.modifyDamageFilteredValue(EnchantmentEffectComponents.DAMAGE, p_343328_, p_344751_, p_342664_, p_344239_, p_345253_, p_344727_); } public void modifyFallBasedDamage(ServerLevel p_344377_, int p_342769_, ItemStack p_344741_, Entity p_344920_, DamageSource p_345151_, MutableFloat p_343049_) { this.modifyDamageFilteredValue(EnchantmentEffectComponents.SMASH_DAMAGE_PER_FALLEN_BLOCK, p_344377_, p_342769_, p_344741_, p_344920_, p_345151_, p_343049_); } public void modifyKnockback(ServerLevel p_345022_, int p_343469_, ItemStack p_343441_, Entity p_345003_, DamageSource p_345200_, MutableFloat p_345434_) { this.modifyDamageFilteredValue(EnchantmentEffectComponents.KNOCKBACK, p_345022_, p_343469_, p_343441_, p_345003_, p_345200_, p_345434_); } public void modifyArmorEffectivness(ServerLevel p_345291_, int p_343247_, ItemStack p_343537_, Entity p_344244_, DamageSource p_344953_, MutableFloat p_345146_) { this.modifyDamageFilteredValue(EnchantmentEffectComponents.ARMOR_EFFECTIVENESS, p_345291_, p_343247_, p_343537_, p_344244_, p_344953_, p_345146_); } public void doPostAttack( ServerLevel p_342826_, int p_343675_, EnchantedItemInUse p_343641_, EnchantmentTarget p_342372_, Entity p_344548_, DamageSource p_342692_ ) { for (TargetedConditionalEffect targetedconditionaleffect : this.getEffects(EnchantmentEffectComponents.POST_ATTACK)) { if (p_342372_ == targetedconditionaleffect.enchanted()) { doPostAttack(targetedconditionaleffect, p_342826_, p_343675_, p_343641_, p_344548_, p_342692_); } } } public static void doPostAttack( TargetedConditionalEffect p_344913_, ServerLevel p_344428_, int p_44688_, EnchantedItemInUse p_344260_, Entity p_44687_, DamageSource p_344028_ ) { if (p_344913_.matches(damageContext(p_344428_, p_44688_, p_44687_, p_344028_))) { Entity entity = switch (p_344913_.affected()) { case ATTACKER -> p_344028_.getEntity(); case DAMAGING_ENTITY -> p_344028_.getDirectEntity(); case VICTIM -> p_44687_; }; if (entity != null) { p_344913_.effect().apply(p_344428_, p_44688_, p_344260_, entity, entity.position()); } } } public void modifyProjectileCount(ServerLevel p_344710_, int p_344927_, ItemStack p_343332_, Entity p_344173_, MutableFloat p_345307_) { this.modifyEntityFilteredValue(EnchantmentEffectComponents.PROJECTILE_COUNT, p_344710_, p_344927_, p_343332_, p_344173_, p_345307_); } public void modifyProjectileSpread(ServerLevel p_342398_, int p_342291_, ItemStack p_345308_, Entity p_343809_, MutableFloat p_343769_) { this.modifyEntityFilteredValue(EnchantmentEffectComponents.PROJECTILE_SPREAD, p_342398_, p_342291_, p_345308_, p_343809_, p_343769_); } public void modifyCrossbowChargeTime(RandomSource p_345467_, int p_343593_, MutableFloat p_343046_) { this.modifyUnfilteredValue(EnchantmentEffectComponents.CROSSBOW_CHARGE_TIME, p_345467_, p_343593_, p_343046_); } public void modifyUnfilteredValue(DataComponentType p_342685_, RandomSource p_344622_, int p_343957_, MutableFloat p_342813_) { EnchantmentValueEffect enchantmentvalueeffect = this.effects.get(p_342685_); if (enchantmentvalueeffect != null) { p_342813_.setValue(enchantmentvalueeffect.process(p_343957_, p_344622_, p_342813_.floatValue())); } } public void tick(ServerLevel p_345036_, int p_344388_, EnchantedItemInUse p_344279_, Entity p_342497_) { applyEffects( this.getEffects(EnchantmentEffectComponents.TICK), entityContext(p_345036_, p_344388_, p_342497_, p_342497_.position()), p_342906_ -> p_342906_.apply(p_345036_, p_344388_, p_344279_, p_342497_, p_342497_.position()) ); } public void onProjectileSpawned(ServerLevel p_344400_, int p_344273_, EnchantedItemInUse p_342998_, Entity p_344540_) { applyEffects( this.getEffects(EnchantmentEffectComponents.PROJECTILE_SPAWNED), entityContext(p_344400_, p_344273_, p_344540_, p_344540_.position()), p_344229_ -> p_344229_.apply(p_344400_, p_344273_, p_342998_, p_344540_, p_344540_.position()) ); } public void onHitBlock(ServerLevel p_343964_, int p_343622_, EnchantedItemInUse p_344872_, Entity p_342891_, Vec3 p_344312_, BlockState p_345016_) { applyEffects( this.getEffects(EnchantmentEffectComponents.HIT_BLOCK), blockHitContext(p_343964_, p_343622_, p_342891_, p_344312_, p_345016_), p_343722_ -> p_343722_.apply(p_343964_, p_343622_, p_344872_, p_342891_, p_344312_) ); } private void modifyItemFilteredCount( DataComponentType>> p_342071_, ServerLevel p_342667_, int p_344856_, ItemStack p_343442_, MutableFloat p_342223_ ) { applyEffects( this.getEffects(p_342071_), itemContext(p_342667_, p_344856_, p_343442_), p_390850_ -> p_342223_.setValue(p_390850_.process(p_344856_, p_342667_.getRandom(), p_342223_.getValue())) ); } private void modifyEntityFilteredValue( DataComponentType>> p_343552_, ServerLevel p_344107_, int p_342319_, ItemStack p_342576_, Entity p_343285_, MutableFloat p_342059_ ) { applyEffects( this.getEffects(p_343552_), entityContext(p_344107_, p_342319_, p_343285_, p_343285_.position()), p_344133_ -> p_342059_.setValue(p_344133_.process(p_342319_, p_343285_.getRandom(), p_342059_.floatValue())) ); } private void modifyDamageFilteredValue( DataComponentType>> p_342460_, ServerLevel p_344318_, int p_343892_, ItemStack p_345407_, Entity p_343559_, DamageSource p_344560_, MutableFloat p_344658_ ) { applyEffects( this.getEffects(p_342460_), damageContext(p_344318_, p_343892_, p_343559_, p_344560_), p_344340_ -> p_344658_.setValue(p_344340_.process(p_343892_, p_343559_.getRandom(), p_344658_.floatValue())) ); } public static LootContext damageContext(ServerLevel p_342651_, int p_344201_, Entity p_345425_, DamageSource p_343766_) { LootParams lootparams = new LootParams.Builder(p_342651_) .withParameter(LootContextParams.THIS_ENTITY, p_345425_) .withParameter(LootContextParams.ENCHANTMENT_LEVEL, p_344201_) .withParameter(LootContextParams.ORIGIN, p_345425_.position()) .withParameter(LootContextParams.DAMAGE_SOURCE, p_343766_) .withOptionalParameter(LootContextParams.ATTACKING_ENTITY, p_343766_.getEntity()) .withOptionalParameter(LootContextParams.DIRECT_ATTACKING_ENTITY, p_343766_.getDirectEntity()) .create(LootContextParamSets.ENCHANTED_DAMAGE); return new LootContext.Builder(lootparams).create(Optional.empty()); } private static LootContext itemContext(ServerLevel p_344430_, int p_344526_, ItemStack p_343134_) { LootParams lootparams = new LootParams.Builder(p_344430_) .withParameter(LootContextParams.TOOL, p_343134_) .withParameter(LootContextParams.ENCHANTMENT_LEVEL, p_344526_) .create(LootContextParamSets.ENCHANTED_ITEM); return new LootContext.Builder(lootparams).create(Optional.empty()); } private static LootContext locationContext(ServerLevel p_342658_, int p_342243_, Entity p_345215_, boolean p_342535_) { LootParams lootparams = new LootParams.Builder(p_342658_) .withParameter(LootContextParams.THIS_ENTITY, p_345215_) .withParameter(LootContextParams.ENCHANTMENT_LEVEL, p_342243_) .withParameter(LootContextParams.ORIGIN, p_345215_.position()) .withParameter(LootContextParams.ENCHANTMENT_ACTIVE, p_342535_) .create(LootContextParamSets.ENCHANTED_LOCATION); return new LootContext.Builder(lootparams).create(Optional.empty()); } private static LootContext entityContext(ServerLevel p_342654_, int p_343984_, Entity p_342853_, Vec3 p_343585_) { LootParams lootparams = new LootParams.Builder(p_342654_) .withParameter(LootContextParams.THIS_ENTITY, p_342853_) .withParameter(LootContextParams.ENCHANTMENT_LEVEL, p_343984_) .withParameter(LootContextParams.ORIGIN, p_343585_) .create(LootContextParamSets.ENCHANTED_ENTITY); return new LootContext.Builder(lootparams).create(Optional.empty()); } private static LootContext blockHitContext(ServerLevel p_342041_, int p_344013_, Entity p_345496_, Vec3 p_343741_, BlockState p_342321_) { LootParams lootparams = new LootParams.Builder(p_342041_) .withParameter(LootContextParams.THIS_ENTITY, p_345496_) .withParameter(LootContextParams.ENCHANTMENT_LEVEL, p_344013_) .withParameter(LootContextParams.ORIGIN, p_343741_) .withParameter(LootContextParams.BLOCK_STATE, p_342321_) .create(LootContextParamSets.HIT_BLOCK); return new LootContext.Builder(lootparams).create(Optional.empty()); } private static void applyEffects(List> p_345356_, LootContext p_343574_, Consumer p_343387_) { for (ConditionalEffect conditionaleffect : p_345356_) { if (conditionaleffect.matches(p_343574_)) { p_343387_.accept(conditionaleffect.effect()); } } } public void runLocationChangedEffects(ServerLevel p_343889_, int p_344660_, EnchantedItemInUse p_344903_, LivingEntity p_342969_) { EquipmentSlot equipmentslot = p_344903_.inSlot(); if (equipmentslot != null) { Map> map = p_342969_.activeLocationDependentEnchantments(equipmentslot); if (!this.matchingSlot(equipmentslot)) { Set set1 = map.remove(this); if (set1 != null) { set1.forEach(p_375302_ -> p_375302_.onDeactivated(p_344903_, p_342969_, p_342969_.position(), p_344660_)); } } else { Set set = map.get(this); for (ConditionalEffect conditionaleffect : this.getEffects(EnchantmentEffectComponents.LOCATION_CHANGED)) { EnchantmentLocationBasedEffect enchantmentlocationbasedeffect = conditionaleffect.effect(); boolean flag = set != null && set.contains(enchantmentlocationbasedeffect); if (conditionaleffect.matches(locationContext(p_343889_, p_344660_, p_342969_, flag))) { if (!flag) { if (set == null) { set = new ObjectArraySet<>(); map.put(this, set); } set.add(enchantmentlocationbasedeffect); } enchantmentlocationbasedeffect.onChangedBlock(p_343889_, p_344660_, p_344903_, p_342969_, p_342969_.position(), !flag); } else if (set != null && set.remove(enchantmentlocationbasedeffect)) { enchantmentlocationbasedeffect.onDeactivated(p_344903_, p_342969_, p_342969_.position(), p_344660_); } } if (set != null && set.isEmpty()) { map.remove(this); } } } } public void stopLocationBasedEffects(int p_342505_, EnchantedItemInUse p_342723_, LivingEntity p_345268_) { EquipmentSlot equipmentslot = p_342723_.inSlot(); if (equipmentslot != null) { Set set = p_345268_.activeLocationDependentEnchantments(equipmentslot).remove(this); if (set != null) { for (EnchantmentLocationBasedEffect enchantmentlocationbasedeffect : set) { enchantmentlocationbasedeffect.onDeactivated(p_342723_, p_345268_, p_345268_.position(), p_342505_); } } } } public static Enchantment.Builder enchantment(Enchantment.EnchantmentDefinition p_342298_) { return new Enchantment.Builder(p_342298_); } public static class Builder { private final Enchantment.EnchantmentDefinition definition; private HolderSet exclusiveSet = HolderSet.direct(); private final Map, List> effectLists = new HashMap<>(); private final DataComponentMap.Builder effectMapBuilder = DataComponentMap.builder(); public Builder(Enchantment.EnchantmentDefinition p_343724_) { this.definition = p_343724_; } public Enchantment.Builder exclusiveWith(HolderSet p_342789_) { this.exclusiveSet = p_342789_; return this; } public Enchantment.Builder withEffect(DataComponentType>> p_345040_, E p_342593_, LootItemCondition.Builder p_344651_) { this.getEffectsList(p_345040_).add(new ConditionalEffect<>(p_342593_, Optional.of(p_344651_.build()))); return this; } public Enchantment.Builder withEffect(DataComponentType>> p_344612_, E p_343461_) { this.getEffectsList(p_344612_).add(new ConditionalEffect<>(p_343461_, Optional.empty())); return this; } public Enchantment.Builder withEffect( DataComponentType>> p_343061_, EnchantmentTarget p_342247_, EnchantmentTarget p_344619_, E p_344716_, LootItemCondition.Builder p_344245_ ) { this.getEffectsList(p_343061_).add(new TargetedConditionalEffect<>(p_342247_, p_344619_, p_344716_, Optional.of(p_344245_.build()))); return this; } public Enchantment.Builder withEffect( DataComponentType>> p_342938_, EnchantmentTarget p_342145_, EnchantmentTarget p_345458_, E p_344837_ ) { this.getEffectsList(p_342938_).add(new TargetedConditionalEffect<>(p_342145_, p_345458_, p_344837_, Optional.empty())); return this; } public Enchantment.Builder withEffect(DataComponentType> p_342540_, EnchantmentAttributeEffect p_344032_) { this.getEffectsList(p_342540_).add(p_344032_); return this; } public Enchantment.Builder withSpecialEffect(DataComponentType p_342163_, E p_344148_) { this.effectMapBuilder.set(p_342163_, p_344148_); return this; } public Enchantment.Builder withEffect(DataComponentType p_344219_) { this.effectMapBuilder.set(p_344219_, Unit.INSTANCE); return this; } private List getEffectsList(DataComponentType> p_343556_) { return (List)this.effectLists.computeIfAbsent(p_343556_, p_344394_ -> { ArrayList arraylist = new ArrayList<>(); this.effectMapBuilder.set(p_343556_, arraylist); return arraylist; }); } public Enchantment build(ResourceLocation p_343227_) { return new Enchantment(Component.translatable(Util.makeDescriptionId("enchantment", p_343227_)), this.definition, this.exclusiveSet, this.effectMapBuilder.build()); } } public record Cost(int base, int perLevelAboveFirst) { public static final Codec CODEC = RecordCodecBuilder.create( p_345482_ -> p_345482_.group( Codec.INT.fieldOf("base").forGetter(Enchantment.Cost::base), Codec.INT.fieldOf("per_level_above_first").forGetter(Enchantment.Cost::perLevelAboveFirst) ) .apply(p_345482_, Enchantment.Cost::new) ); public int calculate(int p_333351_) { return this.base + this.perLevelAboveFirst * (p_333351_ - 1); } } public record EnchantmentDefinition( HolderSet supportedItems, Optional> primaryItems, int weight, int maxLevel, Enchantment.Cost minCost, Enchantment.Cost maxCost, int anvilCost, List slots ) { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( p_344743_ -> p_344743_.group( RegistryCodecs.homogeneousList(Registries.ITEM).fieldOf("supported_items").forGetter(Enchantment.EnchantmentDefinition::supportedItems), RegistryCodecs.homogeneousList(Registries.ITEM).optionalFieldOf("primary_items").forGetter(Enchantment.EnchantmentDefinition::primaryItems), ExtraCodecs.intRange(1, 1024).fieldOf("weight").forGetter(Enchantment.EnchantmentDefinition::weight), ExtraCodecs.intRange(1, 255).fieldOf("max_level").forGetter(Enchantment.EnchantmentDefinition::maxLevel), Enchantment.Cost.CODEC.fieldOf("min_cost").forGetter(Enchantment.EnchantmentDefinition::minCost), Enchantment.Cost.CODEC.fieldOf("max_cost").forGetter(Enchantment.EnchantmentDefinition::maxCost), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("anvil_cost").forGetter(Enchantment.EnchantmentDefinition::anvilCost), EquipmentSlotGroup.CODEC.listOf().fieldOf("slots").forGetter(Enchantment.EnchantmentDefinition::slots) ) .apply(p_344743_, Enchantment.EnchantmentDefinition::new) ); } }