跳到主要内容
关于本文档

本文档基于 Minecraft 26.1.2 的 NMS 源码分析,详细追踪了附魔系统从注册、写入到运行时生效的完整链路。适合需要通过 NMS 操作附魔系统的插件开发者参考。

Minecraft 26.1.2 附魔链路分析

范围:net.minecraft.world.item.enchantment 为核心,向外追踪到物品写入、附魔台、铁砧、命令、战斗、投射物、钓鱼、方块掉落、经验修补、装备属性、位置/tick 效果等运行链路。
方法标识格式参考:method:包名.类名#方法名(完整参数类型...)返回类型
“字面写法”采用短类名形式:Class#method(ShortParam,...):Return
行号以当前源码目录为准。
说明:每个附魔详情中的“完整注册源码”保留 Enchantments.java 原始字面源码;新增的“关键代码展示(逐行注释)”用于展示链路涉及的关键运行时代码,并对关键代码行写中文注释。

0. 附魔概述表

中文名命名空间 ID最高等级描述
水下速掘aqua_affinityI增加水下挖掘速度
节肢杀手bane_of_arthropodsV对节肢生物造成额外伤害并附加缓慢效果
爆炸保护blast_protectionIV减少受到的爆炸伤害,减少受到的爆炸击退
破甲breachIV降低攻击目标的护甲值对攻击伤害的减少效果
引雷channelingI使三叉戟击中实体时召唤闪电,仅在雷暴且被命中实体暴露于天空下时生效
绑定诅咒binding_curseI受影响物品在装备时不能被卸下,创造模式不受影响
消失诅咒vanishing_curseI在生物死亡时,受影响物品会消失而不掉落
致密densityV增加重锤下落攻击所造成的伤害
深海探索者depth_striderIII增加水下行走速度
效率efficiencyV加快挖掘速度
摔落缓冲feather_fallingIV减少受到的摔落伤害
火焰附加fire_aspectII使被近战攻击目标着火
火焰保护fire_protectionIV减少受到的火焰伤害和着火时间
火矢flameI使射出的箭着火
时运fortuneIII增加方块掉落物的数量或概率
冰霜行者frost_walkerII使在水面行走时产生霜冰,且不会受到踩踏燃烧伤害
穿刺impalingV对敏感目标造成额外伤害
无限infinityI射箭时不会消耗普通箭
击退knockbackII增加近战攻击造成的击退距离
抢夺lootingIII增加生物掉落物的数量或概率
忠诚loyaltyIII使掷出后的三叉戟返回,等级越高返回越快
海之眷顾luck_of_the_seaIII增加钓鱼时获得宝藏的概率
突进lungeIII进行戳刺攻击时在攻击方向上移动一段距离
饵钓lureIII减少钓鱼所需的时间
经验修补mendingI消耗获得的经验以修补工具或盔甲耐久
多重射击multishotI装填时消耗一个物品以装填三个该物品
穿透piercingIV使箭穿过多个实体
力量powerV增加箭伤害
弹射物保护projectile_protectionIV减少受到的弹射物伤害
保护protectionIV减少受到的大多数种类的伤害
冲击punchII增加箭的击退距离
快速装填quick_chargeIII减少弩的填装时间
水下呼吸respirationIII延长水下呼吸时间
激流riptideIII将玩家向掷出三叉戟的方向发射,仅在水中或雨中生效
锋利sharpnessV增加近战攻击伤害
精准采集silk_touchI使部分被开采的方块掉落其方块物品而非普通掉落
亡灵杀手smiteV对亡灵生物造成额外伤害
灵魂疾行soul_speedIII增加玩家在灵魂沙和灵魂土上的移动速度
横扫之刃sweeping_edgeIII增加横扫攻击伤害
迅捷潜行swift_sneakIII提高玩家潜行、爬行时的移动速度
荆棘thornsIII给予攻击者伤害
耐久unbreakingIII减少触发耐久消耗的概率
风爆wind_burstIII使重锤下落时击中目标后产生风爆,将攻击者向上弹起

1. 总体模型

1.1 附魔不是硬编码子类,而是“注册数据 + 效果组件”

核心定义:

  • net/minecraft/world/item/enchantment/Enchantments.java:87:定义所有原版附魔 ResourceKey<Enchantment>
  • net/minecraft/world/item/enchantment/Enchantments.java:131bootstrap 注册每个附魔的适用物品、等级、成本、互斥集合和效果组件。
  • net/minecraft/world/item/enchantment/Enchantment.java:61Enchantment 是 record,字段包含描述、定义、互斥集合和效果组件。
  • net/minecraft/world/item/enchantment/EnchantmentEffectComponents.java:26:所有运行时效果组件类型。
  • net/minecraft/world/item/enchantment/EnchantmentHelper.java:49:所有附魔读写、随机选择、运行时分发的工具入口。

核心对象:

// net/minecraft/world/item/enchantment/Enchantment.java:61
public record Enchantment(Component description, Enchantment.EnchantmentDefinition definition, HolderSet<Enchantment> exclusiveSet, DataComponentMap effects) {

definition 负责“附魔能出现在哪里、最高等级、消耗和铁砧成本”;effects 负责“运行时具体生效”。

1.2 物品上的附魔存储

普通物品使用 DataComponents.ENCHANTMENTS,附魔书使用 DataComponents.STORED_ENCHANTMENTS

method:net.minecraft.world.item.enchantment.EnchantmentHelper#getComponentType(net.minecraft.world.item.ItemStack)net.minecraft.core.component.DataComponentType
字面写法:EnchantmentHelper#getComponentType(ItemStack):DataComponentType<ItemEnchantments>
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:87

private static DataComponentType<ItemEnchantments> getComponentType(ItemStack itemStack) {
return itemStack.is(Items.ENCHANTED_BOOK) ? DataComponents.STORED_ENCHANTMENTS : DataComponents.ENCHANTMENTS;
}

参数:

  • itemStack:待读取或写入附魔组件的物品。

返回:

  • 如果是 ENCHANTED_BOOK,返回 STORED_ENCHANTMENTS
  • 否则返回 ENCHANTMENTS

2. 附魔写入链路

2.1 ItemStack.enchant

method:net.minecraft.world.item.ItemStack#enchant(net.minecraft.core.Holder,int)void
字面写法:ItemStack#enchant(Holder<Enchantment>,int):void
位置:net/minecraft/world/item/ItemStack.java:1227

public void enchant(Holder<Enchantment> enchantment, int level) {
EnchantmentHelper.updateEnchantments(this, enchantments -> enchantments.upgrade(enchantment, level));
}

参数:

  • enchantment:要写入的附魔 holder。
  • level:写入等级;内部 upgrade 会与已有等级取较大值。

说明:

  • 这是很多系统最终落点:附魔台、命令、战利品函数等最终都会调用或等价更新 ItemEnchantments

2.2 EnchantmentHelper.updateEnchantments

method:net.minecraft.world.item.enchantment.EnchantmentHelper#updateEnchantments(net.minecraft.world.item.ItemStack,java.util.function.Consumer,boolean)net.minecraft.world.item.enchantment.ItemEnchantments
字面写法:EnchantmentHelper#updateEnchantments(ItemStack,Consumer<ItemEnchantments.Mutable>,boolean):ItemEnchantments
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:59

public static ItemEnchantments updateEnchantments(ItemStack itemStack, Consumer<ItemEnchantments.Mutable> consumer, boolean createComponentIfMissing) {
DataComponentType<ItemEnchantments> componentType = getComponentType(itemStack);
ItemEnchantments oldEnchantments = createComponentIfMissing
? itemStack.getOrDefault(componentType, ItemEnchantments.EMPTY)
: itemStack.get(componentType);
if (oldEnchantments == null) {
return ItemEnchantments.EMPTY;
} else {
ItemEnchantments.Mutable mutableEnchantments = new ItemEnchantments.Mutable(oldEnchantments);
consumer.accept(mutableEnchantments);
ItemEnchantments newEnchantments = mutableEnchantments.toImmutable();
itemStack.set(componentType, newEnchantments);
return newEnchantments;
}
}

参数:

  • itemStack:被修改附魔的物品。
  • consumer:对 ItemEnchantments.Mutable 执行 set、upgrade、removeIf 等操作的回调。
  • createComponentIfMissing:组件不存在时是否用空附魔组件创建。

返回:

  • 修改后的不可变 ItemEnchantments

2.3 附魔台链路

花费计算

method:net.minecraft.world.item.enchantment.EnchantmentHelper#getEnchantmentCost(net.minecraft.util.RandomSource,int,int,net.minecraft.world.item.ItemStack)int
字面写法:EnchantmentHelper#getEnchantmentCost(RandomSource,int,int,ItemStack):int
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:490

public static int getEnchantmentCost(RandomSource random, int slot, int bookcases, ItemStack itemStack) {
Enchantable enchantable = itemStack.get(DataComponents.ENCHANTABLE);
if (enchantable == null) {
return 0;
} else {
if (bookcases > 15) {
bookcases = 15;
}

int selected = random.nextInt(8) + 1 + (bookcases >> 1) + random.nextInt(bookcases + 1);
if (slot == 0) {
return Math.max(selected / 3, 1);
} else {
return slot == 1 ? selected * 2 / 3 + 1 : Math.max(selected, bookcases * 2);
}
}
}

参数:

  • random:附魔台使用的随机源。
  • slot:附魔台 0/1/2 三个选项槽。
  • bookcases:有效书架数量,最多按 15 计算。
  • itemStack:待附魔物品。

返回:

  • 该选项显示和实际使用的附魔花费等级。

调用位置:

  • net/minecraft/world/inventory/EnchantmentMenu.java:143

候选附魔选择

method:net.minecraft.world.item.enchantment.EnchantmentHelper#selectEnchantment(net.minecraft.util.RandomSource,net.minecraft.world.item.ItemStack,int,java.util.stream.Stream)java.util.List
字面写法:EnchantmentHelper#selectEnchantment(RandomSource,ItemStack,int,Stream<Holder<Enchantment>>):List<EnchantmentInstance>
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:532

public static List<EnchantmentInstance> selectEnchantment(RandomSource random, ItemStack itemStack, int enchantmentCost, Stream<Holder<Enchantment>> source) {
List<EnchantmentInstance> results = Lists.newArrayList();
Enchantable enchantable = itemStack.get(DataComponents.ENCHANTABLE);
if (enchantable == null) {
return results;
} else {
enchantmentCost += 1 + random.nextInt(enchantable.value() / 4 + 1) + random.nextInt(enchantable.value() / 4 + 1);
float randomSpan = (random.nextFloat() + random.nextFloat() - 1.0F) * 0.15F;
enchantmentCost = Mth.clamp(Math.round(enchantmentCost + enchantmentCost * randomSpan), 1, Integer.MAX_VALUE);
List<EnchantmentInstance> enchantments = getAvailableEnchantmentResults(enchantmentCost, itemStack, source);
if (!enchantments.isEmpty()) {
WeightedRandom.getRandomItem(random, enchantments, EnchantmentInstance::weight).ifPresent(results::add);

while (random.nextInt(50) <= enchantmentCost) {
if (!results.isEmpty()) {
filterCompatibleEnchantments(enchantments, results.getLast());
}

if (enchantments.isEmpty()) {
break;
}

WeightedRandom.getRandomItem(random, enchantments, EnchantmentInstance::weight).ifPresent(results::add);
enchantmentCost /= 2;
}
}

return results;
}
}

参数:

  • random:随机源。
  • itemStack:待附魔物品。
  • enchantmentCost:本次附魔成本。
  • source:可选附魔集合,附魔台使用 EnchantmentTags.IN_ENCHANTING_TABLE

返回:

  • 本次选中的附魔列表。

附魔台菜单调用

method:net.minecraft.world.inventory.EnchantmentMenu#getEnchantmentList(net.minecraft.core.RegistryAccess,net.minecraft.world.item.ItemStack,int,int)java.util.List
字面写法:EnchantmentMenu#getEnchantmentList(RegistryAccess,ItemStack,int,int):List<EnchantmentInstance>
位置:net/minecraft/world/inventory/EnchantmentMenu.java:303

private List<EnchantmentInstance> getEnchantmentList(RegistryAccess access, ItemStack itemStack, int slot, int enchantmentCost) {
this.random.setSeed(this.enchantmentSeed.get() + slot);
Optional<HolderSet.Named<Enchantment>> tag = access.lookupOrThrow(Registries.ENCHANTMENT).get(EnchantmentTags.IN_ENCHANTING_TABLE);
if (tag.isEmpty()) {
return List.of();
} else {
List<EnchantmentInstance> list = EnchantmentHelper.selectEnchantment(this.random, itemStack, enchantmentCost, tag.get().stream());
if (itemStack.is(Items.BOOK) && list.size() > 1) {
list.remove(this.random.nextInt(list.size()));
}

return list;
}
}

参数:

  • access:注册表访问器。
  • itemStack:待附魔物品。
  • slot:附魔台选项槽。
  • enchantmentCost:该槽附魔成本。

写入位置:

  • net/minecraft/world/inventory/EnchantmentMenu.java:267:遍历 EnchantItemEvent#getEnchantsToAdd()
  • net/minecraft/world/inventory/EnchantmentMenu.java:270:调用 enchantmentItem.enchant(enchantment, entry.getValue())

2.4 铁砧链路

method:net.minecraft.world.inventory.AnvilMenu#createResult()void
字面写法:AnvilMenu#createResult():void
位置:net/minecraft/world/inventory/AnvilMenu.java:144

关键代码:

ItemEnchantments.Mutable enchantments = new ItemEnchantments.Mutable(EnchantmentHelper.getEnchantmentsForCrafting(result));
ItemEnchantments additionalEnchantments = EnchantmentHelper.getEnchantmentsForCrafting(addition);

for (Entry<Holder<Enchantment>> entry : additionalEnchantments.entrySet()) {
Holder<Enchantment> enchantmentHolder = (Holder<Enchantment>)entry.getKey();
int current = enchantments.getLevel(enchantmentHolder);
int level = entry.getIntValue();
level = current == level ? level + 1 : Math.max(level, current);
Enchantment enchantment = enchantmentHolder.value();
boolean compatible = enchantment.canEnchant(input);
if (this.player.hasInfiniteMaterials() || input.is(Items.ENCHANTED_BOOK)) {
compatible = true;
}

for (Holder<Enchantment> other : enchantments.keySet()) {
if (!other.equals(enchantmentHolder) && !Enchantment.areCompatible(enchantmentHolder, other)) {
compatible = false;
price++;
}
}
}

写回:

EnchantmentHelper.setEnchantments(result, enchantments.toImmutable());

写回位置:net/minecraft/world/inventory/AnvilMenu.java:291

说明:

  • 同等级合并会升一级。
  • 超过最高等级时受 bypassEnchantmentLevelRestriction 影响。
  • 互斥判断走 Enchantment.areCompatible

2.5 /enchant 命令链路

method:net.minecraft.server.commands.EnchantCommand#enchant(net.minecraft.commands.CommandSourceStack,java.util.Collection,net.minecraft.core.Holder,int)int
字面写法:EnchantCommand#enchant(CommandSourceStack,Collection<? extends Entity>,Holder<Enchantment>,int):int
位置:net/minecraft/server/commands/EnchantCommand.java:73

private static int enchant(CommandSourceStack source, Collection<? extends Entity> targets, Holder<Enchantment> enchantmentHolder, int level) throws CommandSyntaxException {
Enchantment enchantment = enchantmentHolder.value();
if (level > enchantment.getMaxLevel()) {
throw ERROR_LEVEL_TOO_HIGH.create(level, enchantment.getMaxLevel());
} else {
int success = 0;

for (Entity entity : targets) {
if (entity instanceof LivingEntity target) {
ItemStack item = target.getMainHandItem();
if (!item.isEmpty()) {
if (enchantment.canEnchant(item)
&& EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(item).keySet(), enchantmentHolder)) {
item.enchant(enchantmentHolder, level);
success++;
}
}
}
}

return success;
}
}

参数:

  • source:命令执行源。
  • targets:目标实体集合。
  • enchantmentHolder:要添加的附魔。
  • level:目标等级。

返回:

  • 成功附魔的实体数量。

3. 运行时效果分发方法

3.1 增伤:modifyDamage

method:net.minecraft.world.item.enchantment.EnchantmentHelper#modifyDamage(net.minecraft.server.level.ServerLevel,net.minecraft.world.item.ItemStack,net.minecraft.world.entity.Entity,net.minecraft.world.damagesource.DamageSource,float)float
字面写法:EnchantmentHelper#modifyDamage(ServerLevel,ItemStack,Entity,DamageSource,float):float
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:178

public static float modifyDamage(ServerLevel serverLevel, ItemStack itemStack, Entity victim, DamageSource damageSource, float damage) {
MutableFloat result = new MutableFloat(damage);
runIterationOnItem(itemStack, (enchantment, level) -> enchantment.value().modifyDamage(serverLevel, level, itemStack, victim, damageSource, result));
return result.floatValue();
}

参数:

  • serverLevel:服务端世界,用于构造 loot context、随机数等。
  • itemStack:攻击来源武器或投射物来源武器。
  • victim:受到伤害的实体。
  • damageSource:伤害来源,包含攻击者、直接攻击实体、伤害类型等。
  • damage:进入附魔修正前的原始伤害。

返回:

  • 被所有 DAMAGE 类型附魔处理后的伤害。

内部进入:

method:net.minecraft.world.item.enchantment.Enchantment#modifyDamage(net.minecraft.server.level.ServerLevel,int,net.minecraft.world.item.ItemStack,net.minecraft.world.entity.Entity,net.minecraft.world.damagesource.DamageSource,org.apache.commons.lang3.mutable.MutableFloat)void
字面写法:Enchantment#modifyDamage(ServerLevel,int,ItemStack,Entity,DamageSource,MutableFloat):void
位置:net/minecraft/world/item/enchantment/Enchantment.java:252

public void modifyDamage(ServerLevel serverLevel, int enchantmentLevel, ItemStack itemStack, Entity victim, DamageSource damageSource, MutableFloat amount) {
this.modifyDamageFilteredValue(EnchantmentEffectComponents.DAMAGE, serverLevel, enchantmentLevel, itemStack, victim, damageSource, amount);
}

典型调用:

  • net/minecraft/server/level/ServerPlayer.java:2866:服务端玩家近战。
  • net/minecraft/world/entity/Mob.java:1614:普通生物近战。
  • net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:466:箭命中。
  • net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:140:投掷三叉戟命中。

3.2 防御:getDamageProtection

method:net.minecraft.world.item.enchantment.EnchantmentHelper#getDamageProtection(net.minecraft.server.level.ServerLevel,net.minecraft.world.entity.LivingEntity,net.minecraft.world.damagesource.DamageSource)float
字面写法:EnchantmentHelper#getDamageProtection(ServerLevel,LivingEntity,DamageSource):float
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:170

public static float getDamageProtection(ServerLevel serverLevel, LivingEntity victim, DamageSource source) {
MutableFloat result = new MutableFloat(0.0F);
runIterationOnEquipment(
victim, (enchantment, level, item) -> enchantment.value().modifyDamageProtection(serverLevel, level, item.itemStack(), victim, source, result)
);
return result.floatValue();
}

参数:

  • serverLevel:服务端世界。
  • victim:穿戴装备、接受伤害的生物。
  • source:伤害来源。

返回:

  • 附魔保护值,随后进入 CombatRules.getDamageAfterMagicAbsorb

调用位置:

  • net/minecraft/world/entity/LivingEntity.java:2280

3.3 攻击后效果:doPostAttackEffectsWithItemSource

method:net.minecraft.world.item.enchantment.EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak(net.minecraft.server.level.ServerLevel,net.minecraft.world.entity.Entity,net.minecraft.world.damagesource.DamageSource,net.minecraft.world.item.ItemStack,java.util.function.Consumer)void
字面写法:EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak(ServerLevel,Entity,DamageSource,ItemStack,Consumer<Item>):void
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:227

public static void doPostAttackEffectsWithItemSourceOnBreak(
ServerLevel serverLevel, Entity victim, DamageSource damageSource, @Nullable ItemStack source, @Nullable Consumer<Item> attackerlessOnBreak
) {
if (victim instanceof LivingEntity livingVictim) {
runIterationOnEquipment(
livingVictim,
(enchantment, level, item) -> enchantment.value().doPostAttack(serverLevel, level, item, EnchantmentTarget.VICTIM, victim, damageSource)
);
}

if (source != null) {
if (damageSource.getEntity() instanceof LivingEntity attacker) {
runIterationOnItem(
source,
EquipmentSlot.MAINHAND,
attacker,
(enchantment, level, item) -> enchantment.value().doPostAttack(serverLevel, level, item, EnchantmentTarget.ATTACKER, victim, damageSource)
);
}
}
}

参数:

  • serverLevel:服务端世界。
  • victim:被命中的实体。
  • damageSource:本次伤害来源。
  • source:攻击者使用的武器;可能为空。
  • attackerlessOnBreak:没有攻击者实体时物品损坏回调。

典型调用:

  • 玩家攻击后:net/minecraft/world/entity/player/Player.java:1127
  • 生物攻击后:net/minecraft/world/entity/Mob.java:1624
  • 各类投射物命中后也调用 EnchantmentHelper.doPostAttackEffects

3.4 耐久损耗:processDurabilityChange

method:net.minecraft.world.item.enchantment.EnchantmentHelper#processDurabilityChange(net.minecraft.server.level.ServerLevel,net.minecraft.world.item.ItemStack,int)int
字面写法:EnchantmentHelper#processDurabilityChange(ServerLevel,ItemStack,int):int
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:96

public static int processDurabilityChange(ServerLevel serverLevel, ItemStack itemStack, int amount) {
MutableFloat modifiedAmount = new MutableFloat(amount);
runIterationOnItem(itemStack, (enchantment, level) -> enchantment.value().modifyDurabilityChange(serverLevel, level, itemStack, modifiedAmount));
return modifiedAmount.intValue();
}

参数:

  • serverLevel:服务端世界。
  • itemStack:即将损耗耐久的物品。
  • amount:原始损耗点数。

返回:

  • ITEM_DAMAGE 附魔处理后的实际损耗。

调用位置:

  • net/minecraft/world/item/ItemStack.java:663

3.5 经验修补:modifyDurabilityToRepairFromXp

method:net.minecraft.world.item.enchantment.EnchantmentHelper#modifyDurabilityToRepairFromXp(net.minecraft.server.level.ServerLevel,net.minecraft.world.item.ItemStack,int)int
字面写法:EnchantmentHelper#modifyDurabilityToRepairFromXp(ServerLevel,ItemStack,int):int
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:326

public static int modifyDurabilityToRepairFromXp(ServerLevel serverLevel, ItemStack item, int durability) {
MutableFloat modifiedDurability = new MutableFloat(durability);
runIterationOnItem(item, (enchantment, level) -> enchantment.value().modifyDurabilityToRepairFromXp(serverLevel, level, item, modifiedDurability));
return Math.max(0, modifiedDurability.intValue());
}

参数:

  • serverLevel:服务端世界。
  • item:被经验修补选中的受损物品。
  • durability:经验值可换算的基础修复量。

返回:

  • REPAIR_WITH_XP 附魔修正后的修复量。

调用位置:

  • net/minecraft/world/entity/ExperienceOrb.java:383

3.6 位置变化效果:runLocationChangedEffects

method:net.minecraft.world.item.enchantment.EnchantmentHelper#runLocationChangedEffects(net.minecraft.server.level.ServerLevel,net.minecraft.world.entity.LivingEntity)void
字面写法:EnchantmentHelper#runLocationChangedEffects(ServerLevel,LivingEntity):void
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:254

public static void runLocationChangedEffects(ServerLevel serverLevel, LivingEntity entity) {
runIterationOnEquipment(entity, (enchantment, level, item) -> enchantment.value().runLocationChangedEffects(serverLevel, level, item, entity));
}

参数:

  • serverLevel:服务端世界。
  • entity:装备附魔物品并发生位置变化的生物。

调用位置:

  • net/minecraft/world/entity/LivingEntity.java:596:实体换方块。
  • net/minecraft/world/entity/LivingEntity.java:3457:装备改变后。
  • net/minecraft/server/level/ServerPlayer.java:2307:旁观模式切回后。

3.7 tick 效果:tickEffects

method:net.minecraft.world.item.enchantment.EnchantmentHelper#tickEffects(net.minecraft.server.level.ServerLevel,net.minecraft.world.entity.LivingEntity)void
字面写法:EnchantmentHelper#tickEffects(ServerLevel,LivingEntity):void
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:270

public static void tickEffects(ServerLevel serverLevel, LivingEntity entity) {
runIterationOnEquipment(entity, (enchantment, level, item) -> enchantment.value().tick(serverLevel, level, item, entity));
}

参数:

  • serverLevel:服务端世界。
  • entity:正在 tick 的生物。

调用位置:

  • net/minecraft/world/entity/LivingEntity.java:470

3.8 弹射物生成:onProjectileSpawned

method:net.minecraft.world.item.enchantment.EnchantmentHelper#onProjectileSpawned(net.minecraft.server.level.ServerLevel,net.minecraft.world.item.ItemStack,net.minecraft.world.entity.projectile.Projectile,java.util.function.Consumer)void
字面写法:EnchantmentHelper#onProjectileSpawned(ServerLevel,ItemStack,Projectile,Consumer<Item>):void
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:306

public static void onProjectileSpawned(ServerLevel serverLevel, ItemStack weapon, Projectile projectileEntity, Consumer<Item> onBreak) {
LivingEntity owner = projectileEntity.getOwner() instanceof LivingEntity le ? le : null;
EnchantedItemInUse item = new EnchantedItemInUse(weapon, null, owner, onBreak);
runIterationOnItem(weapon, (enchantment, level) -> enchantment.value().onProjectileSpawned(serverLevel, level, item, projectileEntity));
}

参数:

  • serverLevel:服务端世界。
  • weapon:发射该投射物的武器或投射物物品。
  • projectileEntity:生成出的投射物实体。
  • onBreak:附魔效果导致物品损坏时的回调。

调用位置:

  • net/minecraft/world/entity/projectile/Projectile.java:253

3.9 命中方块:onHitBlock

method:net.minecraft.world.item.enchantment.EnchantmentHelper#onHitBlock(net.minecraft.server.level.ServerLevel,net.minecraft.world.item.ItemStack,net.minecraft.world.entity.LivingEntity,net.minecraft.world.entity.Entity,net.minecraft.world.entity.EquipmentSlot,net.minecraft.world.phys.Vec3,net.minecraft.world.level.block.state.BlockState,java.util.function.Consumer)void
字面写法:EnchantmentHelper#onHitBlock(ServerLevel,ItemStack,LivingEntity,Entity,EquipmentSlot,Vec3,BlockState,Consumer<Item>):void
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:312

public static void onHitBlock(
ServerLevel serverLevel,
ItemStack weapon,
@Nullable LivingEntity owner,
Entity entity,
@Nullable EquipmentSlot slot,
Vec3 hitLocation,
BlockState hitBlock,
Consumer<Item> onBreak
) {
EnchantedItemInUse item = new EnchantedItemInUse(weapon, slot, owner, onBreak);
runIterationOnItem(weapon, (enchantment, level) -> enchantment.value().onHitBlock(serverLevel, level, item, entity, hitLocation, hitBlock));
}

参数:

  • serverLevel:服务端世界。
  • weapon:命中方块的物品或武器。
  • owner:持有者;投射物可能为空。
  • entity:触发命中方块的实体。
  • slot:装备槽位,可能为空。
  • hitLocation:命中位置。
  • hitBlock:被命中的方块状态。
  • onBreak:物品损坏回调。

调用位置:

  • 玩家左键方块:net/minecraft/server/level/ServerPlayerGameMode.java:252
  • 箭命中方块:net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:599
  • 三叉戟命中方块:net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:170

4. 效果组件执行器

4.1 数值处理器

  • AddValuenet/minecraft/world/item/enchantment/effects/AddValue.java:14,返回 input + value(level)
  • MultiplyValuenet/minecraft/world/item/enchantment/effects/MultiplyValue.java:14,返回 input * factor(level)
  • SetValuenet/minecraft/world/item/enchantment/effects/SetValue.java:14,返回固定 value(level)
  • RemoveBinomialnet/minecraft/world/item/enchantment/effects/RemoveBinomial.java:14,按概率从损耗值中扣减,主要用于耐久。

示例:

// net/minecraft/world/item/enchantment/effects/AddValue.java:14
public float process(int enchantmentLevel, RandomSource random, float inputValue) {
return inputValue + this.value.calculate(enchantmentLevel);
}

4.2 实体效果处理器

  • DamageEntitynet/minecraft/world/item/enchantment/effects/DamageEntity.java:26,造成随机范围伤害。
  • Ignitenet/minecraft/world/item/enchantment/effects/Ignite.java:20,点燃实体。
  • ApplyMobEffectnet/minecraft/world/item/enchantment/effects/ApplyMobEffect.java:37,施加药水效果。
  • ChangeItemDamagenet/minecraft/world/item/enchantment/effects/ChangeItemDamage.java:19,改变物品耐久。
  • ApplyEntityImpulsenet/minecraft/world/item/enchantment/effects/ApplyEntityImpulse.java:24,给实体冲量。
  • ExplodeEffectnet/minecraft/world/item/enchantment/effects/ExplodeEffect.java:61,创建爆炸。
  • PlaySoundEffectnet/minecraft/world/item/enchantment/effects/PlaySoundEffect.java:29,播放声音。
  • SpawnParticlesEffectnet/minecraft/world/item/enchantment/effects/SpawnParticlesEffect.java:57,发送粒子。

4.3 位置效果处理器

  • EnchantmentAttributeEffectnet/minecraft/world/item/enchantment/effects/EnchantmentAttributeEffect.java:40,激活时添加临时属性,失效时移除。
  • ReplaceDisknet/minecraft/world/item/enchantment/effects/ReplaceDisk.java:42,以实体位置为中心替换圆盘区域方块,典型用于冰霜行者。

5. 全部附魔生效链路

5.1 护甲保护类

protection

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:137
  • 效果:DAMAGE_PROTECTIONAddValue(perLevel(1.0F))
  • 计算入口:EnchantmentHelper#getDamageProtection(ServerLevel,LivingEntity,DamageSource):float
  • 生效位置:net/minecraft/world/entity/LivingEntity.java:2280
  • 条件:伤害类型不带 BYPASSES_INVULNERABILITY

fire_protection

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:160
  • 效果 1:火焰伤害 DAMAGE_PROTECTION +2/级
  • 效果 2:ATTRIBUTES 修改 BURNING_TIME,降低燃烧持续时间。
  • 计算入口:EnchantmentHelper#getDamageProtectionItemStack#forEachModifier
  • 生效位置:减伤在 LivingEntity.java:2280;燃烧时间在 LivingEntity.java:4644

feather_falling

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:196
  • 效果:对 DamageTypeTags.IS_FALLDAMAGE_PROTECTION +3/级
  • 生效位置:net/minecraft/world/entity/LivingEntity.java:2280

blast_protection

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:220
  • 效果 1:爆炸伤害 DAMAGE_PROTECTION +2/级
  • 效果 2:EXPLOSION_KNOCKBACK_RESISTANCE +0.15/级
  • 生效位置:减伤在 LivingEntity.java:2280;属性由 ItemStack.java:1239 并入。

projectile_protection

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:254
  • 效果:对 DamageTypeTags.IS_PROJECTILEDAMAGE_PROTECTION +2/级
  • 生效位置:net/minecraft/world/entity/LivingEntity.java:2280

5.2 头盔、水下与靴子移动

respiration

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:273
  • 效果:ATTRIBUTES 添加 OXYGEN_BONUS +1/级
  • 生效位置:net/minecraft/world/entity/LivingEntity.java:638

aqua_affinity

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:297
  • 效果:SUBMERGED_MINING_SPEED 总乘法加成。
  • 生效位置:玩家挖掘速度在 net/minecraft/world/entity/player/Player.java:651

depth_strider

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:347
  • 效果:WATER_MOVEMENT_EFFICIENCY +0.33333334/级
  • 生效位置:水中移动计算在 net/minecraft/world/entity/LivingEntity.java:3010

frost_walker

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:372
  • 效果 1:DAMAGE_IMMUNITY 免疫 BURN_FROM_STEPPING
  • 效果 2:LOCATION_CHANGEDReplaceDisk 把脚下水变霜冰。
  • 触发入口:net/minecraft/world/entity/LivingEntity.java:596
  • 实际换块:net/minecraft/world/item/enchantment/effects/ReplaceDisk.java:42

soul_speed

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:489
  • 效果 1:灵魂方块上临时添加 MOVEMENT_SPEEDMOVEMENT_EFFICIENCY
  • 效果 2:灵魂方块上移动时概率损耗耐久。
  • 效果 3:TICK 粒子和声音。
  • 触发入口:LivingEntity.java:470LivingEntity.java:596

swift_sneak

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:558
  • 效果:SNEAKING_SPEED +0.15/级
  • 生效链路:装备属性通过 ItemStack.java:1239 合入玩家属性。

5.3 诅咒

binding_curse

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:425
  • 效果:PREVENT_ARMOR_CHANGE
  • 生效位置:net/minecraft/world/item/equipment/Equippable.java:130
  • 说明:非创造模式无法正常替换该装备。

vanishing_curse

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1256
  • 效果:PREVENT_EQUIPMENT_DROP
  • 生效位置:net/minecraft/world/entity/Mob.java:1063
  • 说明:装备掉落过滤时如果有该组件则阻止掉落。

5.4 近战伤害与攻击后效果

sharpness

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:582
  • 效果:DAMAGEAddValue(perLevel(1.0F, 0.5F))
  • 计算入口:EnchantmentHelper#modifyDamage(ServerLevel,ItemStack,Entity,DamageSource,float):float
  • 生效位置:玩家 ServerPlayer.java:2866,生物 Mob.java:1614

smite

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:600
  • 效果:对 EntityTypeTags.SENSITIVE_TO_SMITE 目标 DAMAGE +2.5/级
  • 生效位置:同 modifyDamage 链路。

bane_of_arthropods

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:625
  • 效果 1:对 SENSITIVE_TO_BANE_OF_ARTHROPODS 目标 DAMAGE +2.5/级
  • 效果 2:直接攻击后给目标缓慢效果。
  • 实际上效果:net/minecraft/world/item/enchantment/effects/ApplyMobEffect.java:37

knockback

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:667
  • 效果:KNOCKBACK +1/级
  • 计算入口:EnchantmentHelper#modifyKnockback(ServerLevel,ItemStack,Entity,DamageSource,float):float
  • 生效位置:net/minecraft/world/entity/LivingEntity.java:1906

fire_aspect

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:683
  • 效果:直接攻击后点燃目标 4 秒/级
  • 执行器:net/minecraft/world/item/enchantment/effects/Ignite.java:20
  • 额外:属于 SMELTS_LOOT 标签,熟肉掉落判断在 net/minecraft/data/loot/EntityLootSubProvider.java:56

looting

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:706
  • 效果 1:EQUIPMENT_DROPS +0.01/级,提升装备掉落概率。
  • 生效位置:net/minecraft/world/entity/Mob.java:1059
  • 效果 2:实体战利品函数读取等级增加掉落数量。
  • 生效位置:net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java:71

sweeping_edge

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:730
  • 效果:SWEEPING_DAMAGE_RATIO
  • 生效位置:net/minecraft/world/entity/player/Player.java:1200

thorns

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:321
  • 效果:受击方装备触发 POST_ATTACK,对攻击者造成 1–5 荆棘伤害并损耗装备 2 点。
  • 触发入口:EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak
  • 执行器:DamageEntity.java:26ChangeItemDamage.java:19

5.5 工具、方块与掉落

efficiency

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:754
  • 效果:MINING_EFFICIENCY = level^2
  • 生效位置:net/minecraft/world/entity/player/Player.java:632

silk_touch

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:778
  • 效果 1:BLOCK_EXPERIENCE 设为 0,方块经验入口 net/minecraft/world/level/block/Block.java:659
  • 效果 2:通过标签阻止特殊破坏副作用:
    • 蜂巢放蜂:net/minecraft/world/level/block/BeehiveBlock.java:107
    • 陶罐碎裂:net/minecraft/world/level/block/DecoratedPotBlock.java:191
    • 冰融化:net/minecraft/world/level/block/IceBlock.java:52
    • 蠹虫生成:net/minecraft/world/level/block/InfestedBlock.java:64

unbreaking

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:795
  • 效果:ITEM_DAMAGE 通过 RemoveBinomial 减少实际耐久损耗。
  • 计算入口:EnchantmentHelper#processDurabilityChange(ServerLevel,ItemStack,int):int
  • 生效位置:net/minecraft/world/item/ItemStack.java:663

fortune

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:820
  • 效果:注册本身没有 effects 组件。
  • 生效方式:方块战利品表函数直接读取等级。
  • 核心读取:net/minecraft/world/level/storage/loot/functions/ApplyBonusCount.java:63
  • 条件读取:net/minecraft/world/level/storage/loot/predicates/BonusLevelTableCondition.java:37

5.6 弓

power

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:836
  • 效果:箭实体作为 DIRECT_ATTACKERDAMAGE +1 + 0.5*(level-1)
  • 生效位置:net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:466

punch

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:858
  • 效果:箭实体作为 DIRECT_ATTACKERKNOCKBACK +1/级
  • 生效位置:net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:563

flame

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:880
  • 效果:PROJECTILE_SPAWNED 点燃投射物 100 tick。
  • 触发入口:net/minecraft/world/entity/projectile/Projectile.java:253

infinity

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:890
  • 效果:普通箭 AMMO_USE 设为 0。
  • 生效位置:net/minecraft/world/item/ProjectileWeaponItem.java:139

5.7 钓鱼

luck_of_the_sea

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:905
  • 效果:FISHING_LUCK_BONUS +1/级
  • 生效位置:net/minecraft/world/item/FishingRodItem.java:48

lure

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:921
  • 效果:FISHING_TIME_REDUCTION +5/级
  • 生效位置:net/minecraft/world/item/FishingRodItem.java:47

5.8 三叉戟

loyalty

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:937
  • 效果:TRIDENT_RETURN_ACCELERATION +1/级
  • 生效位置:net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:222

impaling

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:953
  • 效果:对 EntityTypeTags.SENSITIVE_TO_IMPALING 目标 DAMAGE +2.5/级
  • 生效位置:ThrownTrident.java:140 或近战 modifyDamage 链路。

riptide

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:977
  • 效果:TRIDENT_SPIN_ATTACK_STRENGTHTRIDENT_SOUND
  • 使用入口:net/minecraft/world/item/TridentItem.java:71
  • 限制入口:net/minecraft/world/item/TridentItem.java:156

channeling

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1049
  • 效果 1:雷暴、可见天空、三叉戟命中实体时召雷。
  • 效果 2:雷暴、命中避雷针方块时召雷。
  • 命中实体后处理:EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak
  • 命中方块入口:net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:170

5.9 弩

multishot

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1100
  • 效果:PROJECTILE_COUNT +2PROJECTILE_SPREAD +10
  • 生效位置:数量在 net/minecraft/world/item/ProjectileWeaponItem.java:122,扩散在 net/minecraft/world/item/ProjectileWeaponItem.java:57

quick_charge

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1118
  • 效果:CROSSBOW_CHARGE_TIME -0.25/级,并提供装填音效列表。
  • 生效位置:net/minecraft/world/item/CrossbowItem.java:249

piercing

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1149
  • 效果:PROJECTILE_PIERCING +1/级
  • 生效位置:net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:123

5.10 重锤与突刺

density

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1166
  • 效果:SMASH_DAMAGE_PER_FALLEN_BLOCK +0.5/级
  • 生效位置:net/minecraft/world/item/MaceItem.java:114

breach

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1183
  • 效果:ARMOR_EFFECTIVENESS -0.15/级
  • 生效位置:net/minecraft/world/damagesource/CombatRules.java:20

wind_burst

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1200
  • 效果:坠落攻击后触发 ExplodeEffect
  • 执行器:net/minecraft/world/item/enchantment/effects/ExplodeEffect.java:61

lunge

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:997
  • 效果:POST_PIERCING_ATTACK,对使用者执行耐久损耗、饥饿消耗、冲量和音效。
  • 触发入口:net/minecraft/world/entity/LivingEntity.java:2066
  • 事件门:net/minecraft/world/item/enchantment/Enchantment.java:306
  • 冲量执行:net/minecraft/world/item/enchantment/effects/ApplyEntityImpulse.java:24

5.11 修补

mending

  • 定义:net/minecraft/world/item/enchantment/Enchantments.java:1240
  • 效果:REPAIR_WITH_XPMultiplyValue(2.0F)
  • 生效位置:net/minecraft/world/entity/ExperienceOrb.java:379
  • 核心链路:
    1. 经验球被玩家拾取。
    2. getRandomItemWith(REPAIR_WITH_XP, player, ItemStack::isDamaged) 随机选装备。
    3. modifyDurabilityToRepairFromXp 计算修复量。
    4. 减少物品 damage value。

6. 互斥集合与可附魔性

6.1 互斥判断

method:net.minecraft.world.item.enchantment.Enchantment#areCompatible(net.minecraft.core.Holder,net.minecraft.core.Holder)boolean
字面写法:Enchantment#areCompatible(Holder<Enchantment>,Holder<Enchantment>):boolean
位置:net/minecraft/world/item/enchantment/Enchantment.java:162

public static boolean areCompatible(Holder<Enchantment> enchantment, Holder<Enchantment> other) {
return !enchantment.equals(other) && !enchantment.value().exclusiveSet.contains(other) && !other.value().exclusiveSet.contains(enchantment);
}

参数:

  • enchantment:第一个附魔。
  • other:第二个附魔。

返回:

  • 二者不是同一个,且互不在对方 exclusiveSet 中时返回 true。

主要互斥定义:

  • 护甲保护互斥:VanillaEnchantmentTagsProvider.java:62
  • 靴子互斥:VanillaEnchantmentTagsProvider.java:64
  • 弓互斥:VanillaEnchantmentTagsProvider.java:65
  • 弩互斥:VanillaEnchantmentTagsProvider.java:66
  • 伤害类互斥:VanillaEnchantmentTagsProvider.java:67
  • 挖掘掉落互斥:VanillaEnchantmentTagsProvider.java:69
  • 激流互斥:VanillaEnchantmentTagsProvider.java:70

6.2 附魔台候选过滤

method:net.minecraft.world.item.enchantment.EnchantmentHelper#getAvailableEnchantmentResults(int,net.minecraft.world.item.ItemStack,java.util.stream.Stream)java.util.List
字面写法:EnchantmentHelper#getAvailableEnchantmentResults(int,ItemStack,Stream<Holder<Enchantment>>):List<EnchantmentInstance>
位置:net/minecraft/world/item/enchantment/EnchantmentHelper.java:577

public static List<EnchantmentInstance> getAvailableEnchantmentResults(int value, ItemStack itemStack, Stream<Holder<Enchantment>> source) {
List<EnchantmentInstance> results = Lists.newArrayList();
boolean isBook = itemStack.is(Items.BOOK);
source.filter(enchantment -> enchantment.value().isPrimaryItem(itemStack) || isBook).forEach(holder -> {
Enchantment enchantment = holder.value();

for (int level = enchantment.getMaxLevel(); level >= enchantment.getMinLevel(); level--) {
if (value >= enchantment.getMinCost(level) && value <= enchantment.getMaxCost(level)) {
results.add(new EnchantmentInstance((Holder<Enchantment>)holder, level));
break;
}
}
});
return results;
}

参数:

  • value:附魔成本值。
  • itemStack:待附魔物品。
  • source:候选附魔 stream。

返回:

  • 当前成本和物品条件下可出现的附魔实例。

7. 附魔效果组件到附魔名称的索引

附魔主要组件主要计算/生效方法
protectionDAMAGE_PROTECTIONgetDamageProtection
fire_protectionDAMAGE_PROTECTION, ATTRIBUTESgetDamageProtection, ItemStack#forEachModifier
feather_fallingDAMAGE_PROTECTIONgetDamageProtection
blast_protectionDAMAGE_PROTECTION, ATTRIBUTESgetDamageProtection, explosion knockback attribute
projectile_protectionDAMAGE_PROTECTIONgetDamageProtection
respirationATTRIBUTESOXYGEN_BONUS
aqua_affinityATTRIBUTESSUBMERGED_MINING_SPEED
thornsPOST_ATTACKdoPostAttackEffects
depth_striderATTRIBUTESWATER_MOVEMENT_EFFICIENCY
frost_walkerDAMAGE_IMMUNITY, LOCATION_CHANGEDisImmuneToDamage, runLocationChangedEffects
binding_cursePREVENT_ARMOR_CHANGEEquippable#swapWithEquipmentSlot
soul_speedLOCATION_CHANGED, TICKrunLocationChangedEffects, tickEffects
swift_sneakATTRIBUTESSNEAKING_SPEED
sharpnessDAMAGEmodifyDamage
smiteDAMAGEmodifyDamage
bane_of_arthropodsDAMAGE, POST_ATTACKmodifyDamage, doPostAttackEffects
knockbackKNOCKBACKmodifyKnockback
fire_aspectPOST_ATTACK, tag SMELTS_LOOTdoPostAttackEffects, loot predicate
lootingEQUIPMENT_DROPS, loot functionsprocessEquipmentDropChance, loot count functions
sweeping_edgeATTRIBUTESSWEEPING_DAMAGE_RATIO
efficiencyATTRIBUTESMINING_EFFICIENCY
silk_touchBLOCK_EXPERIENCE, tagsblock loot / special block logic
unbreakingITEM_DAMAGEprocessDurabilityChange
fortuneloot functionsApplyBonusCount
powerDAMAGEAbstractArrow#onHitEntity
punchKNOCKBACKAbstractArrow#onHitEntity
flamePROJECTILE_SPAWNEDProjectile#applyOnProjectileSpawned
infinityAMMO_USEProjectileWeaponItem#useAmmo
luck_of_the_seaFISHING_LUCK_BONUSFishingRodItem#use
lureFISHING_TIME_REDUCTIONFishingRodItem#use
loyaltyTRIDENT_RETURN_ACCELERATIONThrownTrident#getLoyaltyFromItem
impalingDAMAGEmodifyDamage
riptideTRIDENT_SPIN_ATTACK_STRENGTH, TRIDENT_SOUNDTridentItem#releaseUsing
channelingPOST_ATTACK, HIT_BLOCKtrident hit entity/block
multishotPROJECTILE_COUNT, PROJECTILE_SPREADProjectileWeaponItem#draw, shoot
quick_chargeCROSSBOW_CHARGE_TIME, CROSSBOW_CHARGING_SOUNDSCrossbowItem#getChargeDuration
piercingPROJECTILE_PIERCINGAbstractArrow constructor
densitySMASH_DAMAGE_PER_FALLEN_BLOCKMaceItem#getAttackDamageBonus
breachARMOR_EFFECTIVENESSCombatRules#getDamageAfterAbsorb
wind_burstPOST_ATTACK + ExplodeEffectdoPostAttackEffects
lungePOST_PIERCING_ATTACKLivingEntity#postPiercingAttack
mendingREPAIR_WITH_XPExperienceOrb#repairPlayerItems
vanishing_cursePREVENT_EQUIPMENT_DROPdeath/equipment drop filtering

6.1 保护 protection

  • 中文名:保护
  • 命名空间 ID:protection
  • 最高等级:IV
  • 描述:减少受到的大多数种类的伤害。
  • 适用物品:盔甲;代码为 ItemTags.ARMOR_ENCHANTABLE,槽位 EquipmentSlotGroup.ARMOR。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:137

详细生效链路

  1. 注册为 DAMAGE_PROTECTION,每级 AddValue(1.0F),过滤条件排除 DamageTypeTags.BYPASSES_INVULNERABILITY
  2. 实体受伤进入 LivingEntity#getDamageAfterMagicAbsorb(DamageSource,float):float;若伤害不绕过附魔,调用 EnchantmentHelper#getDamageProtection(ServerLevel,LivingEntity,DamageSource):float
  3. getDamageProtection 遍历受害者所有装备槽,匹配 ARMOR 槽位后调用 Enchantment#modifyDamageProtection
  4. Enchantment#modifyDamageProtection 构造 ENCHANTED_DAMAGE 上下文,条件通过后把保护值累计到 MutableFloat
  5. 最终 LivingEntity#getDamageAfterMagicAbsorb 把累计保护值交给 CombatRules#getDamageAfterMagicAbsorb 计算最终减伤结果。

关键代码展示(逐行注释)

// net/minecraft/world/entity/LivingEntity.java:2270
protected float getDamageAfterMagicAbsorb(DamageSource damageSource, float damage) { // 进入“附魔减伤”阶段
if (damageSource.is(DamageTypeTags.BYPASSES_EFFECTS)) { // 完全绕过效果类防御时
return damage; // 直接返回原伤害
} else if (damage <= 0.0F) { // 非正伤害无需继续结算
return 0.0F; // 直接归零
} else if (damageSource.is(DamageTypeTags.BYPASSES_ENCHANTMENTS)) { // 绕过附魔时
return damage; // 保护类附魔完全不参与
} else { // 允许进入附魔防御链路
float enchantmentArmor; // 这里保存“附魔提供的保护值”
if (this.level() instanceof ServerLevel serverLevel) { // 只有服务端才做正式附魔计算
enchantmentArmor = EnchantmentHelper.getDamageProtection(serverLevel, this, damageSource); // 汇总全身装备上的保护类附魔
} else { // 客户端不做这套正式结算
enchantmentArmor = 0.0F; // 默认没有附魔保护
}

if (enchantmentArmor > 0.0F) { // 只有确实拿到保护值时
damage = CombatRules.getDamageAfterMagicAbsorb(damage, enchantmentArmor); // 按保护值缩减最终伤害
}

return damage; // 返回经过附魔减伤后的伤害
}
}

完整注册源码

      register(// 137
context,
PROTECTION,
Enchantment.enchantment(// 140
Enchantment.definition(// 141
items.getOrThrow(ItemTags.ARMOR_ENCHANTABLE),// 142
10,
4,
Enchantment.dynamicCost(1, 11),// 145
Enchantment.dynamicCost(12, 11),// 146
1,
EquipmentSlotGroup.ARMOR
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.ARMOR_EXCLUSIVE))// 151
.withEffect(// 152
EnchantmentEffectComponents.DAMAGE_PROTECTION,
new AddValue(LevelBasedValue.perLevel(1.0F)),// 154
DamageSourceCondition.hasDamageSource(// 155
DamageSourcePredicate.Builder.damageType().tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY))// 156
)
)
);

6.2 火焰保护 fire_protection

  • 中文名:火焰保护
  • 命名空间 ID:fire_protection
  • 最高等级:IV
  • 描述:减少受到的火焰伤害和着火时间。
  • 适用物品:盔甲;ItemTags.ARMOR_ENCHANTABLE,槽位 ARMOR。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:160

详细生效链路

  1. 注册为火焰条件下的 DAMAGE_PROTECTION,每级 AddValue(2.0F),仅匹配 DamageTypeTags.IS_FIRE
  2. 减伤链路与保护相同:LivingEntity#getDamageAfterMagicAbsorb -> EnchantmentHelper#getDamageProtection -> Enchantment#modifyDamageProtection
  3. 额外注册 ATTRIBUTESAttributes.BURNING_TIME,每级 -0.15F,操作为 ADD_MULTIPLIED_BASE
  4. 装备属性由 ItemStack#forEachModifier 合并 EnchantmentHelper#forEachModifier 注入实体属性。
  5. 实体被点燃时 LivingEntity#igniteForTicks(int):voidBURNING_TIME 属性缩放燃烧 tick,因此着火时间变短。

关键代码展示(逐行注释)

// net/minecraft/world/entity/LivingEntity.java:4645
public void igniteForTicks(int numberOfTicks) { // 所有“设置燃烧时间”的入口最终会走到这里
super.igniteForTicks( // 调用父类真正写入燃烧时长
Mth.ceil(numberOfTicks * this.getAttributeValue(Attributes.BURNING_TIME)) // 用 BURNING_TIME 属性缩放原始燃烧 tick
);
}

完整注册源码

      register(// 160
context,
FIRE_PROTECTION,
Enchantment.enchantment(// 163
Enchantment.definition(// 164
items.getOrThrow(ItemTags.ARMOR_ENCHANTABLE),// 165
5,
4,
Enchantment.dynamicCost(10, 8),// 168
Enchantment.dynamicCost(18, 8),// 169
2,
EquipmentSlotGroup.ARMOR
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.ARMOR_EXCLUSIVE))// 174
.withEffect(// 175
EnchantmentEffectComponents.DAMAGE_PROTECTION,
new AddValue(LevelBasedValue.perLevel(2.0F)),// 177
AllOfCondition.allOf(// 178
DamageSourceCondition.hasDamageSource(// 179
DamageSourcePredicate.Builder.damageType()// 180
.tag(TagPredicate.is(DamageTypeTags.IS_FIRE))// 181
.tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY))// 182
)
)
)
.withEffect(// 186
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.fire_protection"),// 189
Attributes.BURNING_TIME,
LevelBasedValue.perLevel(-0.15F),// 191
AttributeModifier.Operation.ADD_MULTIPLIED_BASE
)
)
);

6.3 摔落缓冲 feather_falling

  • 中文名:摔落缓冲
  • 命名空间 ID:feather_falling
  • 最高等级:IV
  • 描述:减少受到的摔落伤害。
  • 适用物品:脚部盔甲;ItemTags.FOOT_ARMOR_ENCHANTABLE,槽位 ARMOR。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:196

详细生效链路

  1. 注册为 DAMAGE_PROTECTION,每级 AddValue(3.0F),仅匹配 DamageTypeTags.IS_FALL
  2. 摔落伤害在实体通用受伤流程里进入 LivingEntity#getDamageAfterMagicAbsorb
  3. EnchantmentHelper#getDamageProtection 遍历受害者装备并调用 Enchantment#modifyDamageProtection
  4. loot context 中 DAMAGE_SOURCE 被判定为 fall 后,摔落缓冲的保护值累计。
  5. 累计保护值参与最终附魔减伤,因此实际摔落伤害降低。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/EnchantmentHelper.java:170
public static float getDamageProtection(ServerLevel serverLevel, LivingEntity victim, DamageSource source) { // 汇总受害者身上所有保护类附魔
MutableFloat result = new MutableFloat(0.0F); // 从 0 开始累计保护值
runIterationOnEquipment( // 遍历盔甲、主副手等全部装备槽
victim, // 当前受击实体
(enchantment, level, item) -> enchantment.value().modifyDamageProtection(serverLevel, level, item.itemStack(), victim, source, result) // 让每个附魔按伤害类型决定是否加值
);
return result.floatValue(); // 返回累计后的总保护值
}

完整注册源码

      register(// 196
context,
FEATHER_FALLING,
Enchantment.enchantment(// 199
Enchantment.definition(// 200
items.getOrThrow(ItemTags.FOOT_ARMOR_ENCHANTABLE),// 201
5,
4,
Enchantment.dynamicCost(5, 6),// 204
Enchantment.dynamicCost(11, 6),// 205
2,
EquipmentSlotGroup.ARMOR
)
)
.withEffect(// 210
EnchantmentEffectComponents.DAMAGE_PROTECTION,
new AddValue(LevelBasedValue.perLevel(3.0F)),// 212
DamageSourceCondition.hasDamageSource(// 213
DamageSourcePredicate.Builder.damageType()// 214
.tag(TagPredicate.is(DamageTypeTags.IS_FALL))// 215
.tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY))// 216
)
)
);

6.4 爆炸保护 blast_protection

  • 中文名:爆炸保护
  • 命名空间 ID:blast_protection
  • 最高等级:IV
  • 描述:减少受到的爆炸伤害,并减少受到的爆炸击退。
  • 适用物品:盔甲;ItemTags.ARMOR_ENCHANTABLE,槽位 ARMOR。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:220

详细生效链路

  1. 注册为爆炸条件下的 DAMAGE_PROTECTION,每级 AddValue(2.0F),匹配 DamageTypeTags.IS_EXPLOSION
  2. 爆炸伤害进入 LivingEntity#getDamageAfterMagicAbsorb 时,通过 EnchantmentHelper#getDamageProtection 叠加保护值。
  3. 额外注册 ATTRIBUTESAttributes.EXPLOSION_KNOCKBACK_RESISTANCE,每级 +0.15F
  4. 属性通过 ItemStack#forEachModifier -> EnchantmentHelper#forEachModifier 注入实体属性表。
  5. 爆炸击退逻辑读取该属性,因此不仅伤害降低,击退也会被削弱。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/Enchantments.java:244
.withEffect( // 继续给爆炸保护挂第二条效果链
EnchantmentEffectComponents.ATTRIBUTES, // 这条链属于“属性修饰符”
new EnchantmentAttributeEffect( // 创建一个附魔属性效果
Identifier.withDefaultNamespace("enchantment.blast_protection"), // 该修饰符的唯一标识
Attributes.EXPLOSION_KNOCKBACK_RESISTANCE, // 修改的是“爆炸击退抗性”属性
LevelBasedValue.perLevel(0.15F), // 每级提升 0.15
AttributeModifier.Operation.ADD_VALUE // 直接按数值相加
)
)

完整注册源码

      register(// 220
context,
BLAST_PROTECTION,
Enchantment.enchantment(// 223
Enchantment.definition(// 224
items.getOrThrow(ItemTags.ARMOR_ENCHANTABLE),// 225
2,
4,
Enchantment.dynamicCost(5, 8),// 228
Enchantment.dynamicCost(13, 8),// 229
4,
EquipmentSlotGroup.ARMOR
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.ARMOR_EXCLUSIVE))// 234
.withEffect(// 235
EnchantmentEffectComponents.DAMAGE_PROTECTION,
new AddValue(LevelBasedValue.perLevel(2.0F)),// 237
DamageSourceCondition.hasDamageSource(// 238
DamageSourcePredicate.Builder.damageType()// 239
.tag(TagPredicate.is(DamageTypeTags.IS_EXPLOSION))// 240
.tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY))// 241
)
)
.withEffect(// 244
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.blast_protection"),// 247
Attributes.EXPLOSION_KNOCKBACK_RESISTANCE,
LevelBasedValue.perLevel(0.15F),// 249
AttributeModifier.Operation.ADD_VALUE
)
)
);

6.5 弹射物保护 projectile_protection

  • 中文名:弹射物保护
  • 命名空间 ID:projectile_protection
  • 最高等级:IV
  • 描述:减少受到的弹射物伤害。
  • 适用物品:盔甲;ItemTags.ARMOR_ENCHANTABLE,槽位 ARMOR。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:254

详细生效链路

  1. 注册为 DAMAGE_PROTECTION,每级 AddValue(2.0F),仅匹配 DamageTypeTags.IS_PROJECTILE
  2. 箭、三叉戟等造成的伤害在实体防御阶段进入 LivingEntity#getDamageAfterMagicAbsorb
  3. helper 遍历受害者装备,调用 Enchantment#modifyDamageProtection
  4. 只有当 DAMAGE_SOURCE 被判定为 projectile 时才累计保护值。
  5. 最终返回的保护值用于减小弹射物造成的伤害。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/Enchantments.java:269
.withEffect( // 给弹射物保护注册效果
EnchantmentEffectComponents.DAMAGE_PROTECTION, // 这是“附魔减伤值”组件
new AddValue(LevelBasedValue.perLevel(2.0F)), // 每级提供 2 点保护值
DamageSourceCondition.hasDamageSource( // 只有满足伤害来源条件才生效
DamageSourcePredicate.Builder.damageType() // 开始构造伤害类型谓词
.tag(TagPredicate.is(DamageTypeTags.IS_PROJECTILE)) // 要求伤害必须是弹射物伤害
.tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY)) // 同时不能是完全绕过防御的伤害
)
)

完整注册源码

      register(// 254
context,
PROJECTILE_PROTECTION,
Enchantment.enchantment(// 257
Enchantment.definition(// 258
items.getOrThrow(ItemTags.ARMOR_ENCHANTABLE), 5, 4, Enchantment.dynamicCost(3, 6), Enchantment.dynamicCost(9, 6), 2, EquipmentSlotGroup.ARMOR// 259 262 263
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.ARMOR_EXCLUSIVE))// 268
.withEffect(// 269
EnchantmentEffectComponents.DAMAGE_PROTECTION,
new AddValue(LevelBasedValue.perLevel(2.0F)),// 271
DamageSourceCondition.hasDamageSource(// 272
DamageSourcePredicate.Builder.damageType()// 273
.tag(TagPredicate.is(DamageTypeTags.IS_PROJECTILE))// 274
.tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY))// 275
)
)
);

6.6 水下呼吸 respiration

  • 中文名:水下呼吸
  • 命名空间 ID:respiration
  • 最高等级:III
  • 描述:延长水下呼吸时间。
  • 适用物品:头部盔甲;ItemTags.HEAD_ARMOR_ENCHANTABLE,槽位 HEAD。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:273

详细生效链路

  1. 注册 ATTRIBUTESAttributes.OXYGEN_BONUS,每级 +1.0F
  2. 装备后,ItemStack#forEachModifier 会把附魔属性和物品原生属性一起交给实体属性系统。
  3. EnchantmentHelper#forEachModifier 读取 ATTRIBUTES 组件并为当前槽位生成 AttributeModifier
  4. 实体的空气/溺水逻辑读取 Attributes.OXYGEN_BONUS,关键读取位置在 LivingEntity.java:638
  5. 因此该附魔通过属性长期提高氧气缓冲,而不是通过 tick 主动恢复空气。

关键代码展示(逐行注释)

// net/minecraft/world/entity/LivingEntity.java:637
protected int decreaseAirSupply(int currentSupply) { // 每次需要扣空气时会走到这里
AttributeInstance respiration = this.getAttribute(Attributes.OXYGEN_BONUS); // 读取氧气缓冲属性
double oxygenBonus; // 保存属性值
if (respiration != null) { // 正常情况下头盔附魔会把属性挂进来
oxygenBonus = respiration.getValue(); // 取出当前总氧气加成
} else { // 没有该属性实例时
oxygenBonus = 0.0; // 视为无加成
}

return oxygenBonus > 0.0 && this.random.nextDouble() >= 1.0 / (oxygenBonus + 1.0) ? currentSupply : currentSupply - 1; // 有加成时按概率“本次不扣空气”
}

完整注册源码

      register(// 279
context,
RESPIRATION,
Enchantment.enchantment(// 282
Enchantment.definition(// 283
items.getOrThrow(ItemTags.HEAD_ARMOR_ENCHANTABLE),// 284
2,
3,
Enchantment.dynamicCost(10, 10),// 287
Enchantment.dynamicCost(40, 10),// 288
4,
EquipmentSlotGroup.HEAD
)
)
.withEffect(// 293
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.respiration"),// 296
Attributes.OXYGEN_BONUS,
LevelBasedValue.perLevel(1.0F),// 298
AttributeModifier.Operation.ADD_VALUE
)
)
);

6.7 水下速掘 aqua_affinity

  • 中文名:水下速掘
  • 命名空间 ID:aqua_affinity
  • 最高等级:I
  • 描述:增加水下挖掘速度。
  • 适用物品:头部盔甲;ItemTags.HEAD_ARMOR_ENCHANTABLE,槽位 HEAD。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:297

详细生效链路

  1. 注册 ATTRIBUTESAttributes.SUBMERGED_MINING_SPEED,数值为 +4.0F,操作为 ADD_MULTIPLIED_TOTAL
  2. 装备属性注入链路为 ItemStack#forEachModifier -> EnchantmentHelper#forEachModifier
  3. 玩家计算挖掘速度时会读取 SUBMERGED_MINING_SPEED,关键位置在 Player.java:651
  4. 无该附魔时水下挖掘有明显惩罚;该属性提高水下挖掘倍率。
  5. 所以它是纯属性型附魔,不走攻击、tick、命中方块等事件链路。

关键代码展示(逐行注释)

// net/minecraft/world/entity/player/Player.java:629
public float getDestroySpeed(BlockState state) { // 玩家计算挖掘速度的核心方法
float speed = this.inventory.getSelectedItem().getDestroySpeed(state); // 先取工具对当前方块的基础挖掘速度
if (speed > 1.0F) { // 真正适配工具时
speed += (float)this.getAttributeValue(Attributes.MINING_EFFICIENCY); // 叠加效率附魔带来的挖掘效率属性
}

speed *= (float)this.getAttributeValue(Attributes.BLOCK_BREAK_SPEED); // 再叠加通用破坏速度属性
if (this.isEyeInFluid(FluidTags.WATER)) { // 进入水下挖掘分支时
speed *= (float)this.getAttribute(Attributes.SUBMERGED_MINING_SPEED).getValue(); // 用水下挖掘速度属性缩放最终速度
}

if (!this.onGround()) { // 不在地面时还有空中惩罚
speed /= 5.0F; // 额外除以 5
}
}

完整注册源码

      register(// 303
context,
AQUA_AFFINITY,
Enchantment.enchantment(// 306
Enchantment.definition(// 307
items.getOrThrow(ItemTags.HEAD_ARMOR_ENCHANTABLE),// 308
2,
1,
Enchantment.constantCost(1),// 311
Enchantment.constantCost(41),// 312
4,
EquipmentSlotGroup.HEAD
)
)
.withEffect(// 317
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.aqua_affinity"),// 320
Attributes.SUBMERGED_MINING_SPEED,
LevelBasedValue.perLevel(4.0F),// 322
AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL
)
)
);

6.8 荆棘 thorns

  • 中文名:荆棘
  • 命名空间 ID:thorns
  • 最高等级:III
  • 描述:给予攻击者伤害。
  • 适用物品:盔甲;supported 为 ARMOR_ENCHANTABLE,primary 为 CHEST_ARMOR_ENCHANTABLE,槽位 ANY。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:321

详细生效链路

  1. 注册 POST_ATTACK,声明 enchanted=VICTIM,affected=ATTACKER。
  2. 实体被攻击且伤害成功后,EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak 先遍历受害者装备。
  3. 如果装备有荆棘,Enchantment#doPostAttack 检查随机概率 0.15 * level
  4. 条件通过后执行 DamageEntity(1..5, DamageTypes.THORNS) 对攻击者反伤。
  5. 同一个效果组里还执行 ChangeItemDamage(2),通过 ItemStack#hurtAndBreak 消耗触发荆棘的装备耐久。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/EnchantmentHelper.java:227
public static void doPostAttackEffectsWithItemSourceOnBreak( // 近战/投射物命中成功后的附魔后处理入口
ServerLevel serverLevel, Entity victim, DamageSource damageSource, @Nullable ItemStack source, @Nullable Consumer<Item> attackerlessOnBreak
) {
if (victim instanceof LivingEntity livingVictim) { // 如果受击方是活体
runIterationOnEquipment( // 先遍历受击方全身装备
livingVictim, // 这里就是“被打的人”
(enchantment, level, item) -> enchantment.value().doPostAttack(serverLevel, level, item, EnchantmentTarget.VICTIM, victim, damageSource) // 受击方装备上的荆棘就在这里触发
);
}

if (source != null) { // 如果攻击方有明确武器
if (damageSource.getEntity() instanceof LivingEntity attacker) { // 且攻击来源是活体
runIterationOnItem( // 再遍历攻击武器上的附魔
source, // 当前武器
EquipmentSlot.MAINHAND, // 主手槽位
attacker, // 攻击者实体
(enchantment, level, item) -> enchantment.value().doPostAttack(serverLevel, level, item, EnchantmentTarget.ATTACKER, victim, damageSource) // 火焰附加、击退等会走这里
);
}
}
}

完整注册源码

      register(// 327
context,
THORNS,
Enchantment.enchantment(// 330
Enchantment.definition(// 331
items.getOrThrow(ItemTags.ARMOR_ENCHANTABLE),// 332
items.getOrThrow(ItemTags.CHEST_ARMOR_ENCHANTABLE),// 333
1,
3,
Enchantment.dynamicCost(10, 20),// 336
Enchantment.dynamicCost(60, 20),// 337
8,
EquipmentSlotGroup.ANY
)
)
.withEffect(// 342
EnchantmentEffectComponents.POST_ATTACK,
EnchantmentTarget.VICTIM,
EnchantmentTarget.ATTACKER,
AllOf.entityEffects(// 346
new DamageEntity(LevelBasedValue.constant(1.0F), LevelBasedValue.constant(5.0F), damageTypes.getOrThrow(DamageTypes.THORNS)),// 347
new ChangeItemDamage(LevelBasedValue.constant(2.0F))// 348
),
LootItemRandomChanceCondition.randomChance(EnchantmentLevelProvider.forEnchantmentLevel(LevelBasedValue.perLevel(0.15F)))// 350
)
);

6.9 深海探索者 depth_strider

  • 中文名:深海探索者
  • 命名空间 ID:depth_strider
  • 最高等级:III
  • 描述:增加水下行走速度。
  • 适用物品:脚部盔甲;ItemTags.FOOT_ARMOR_ENCHANTABLE,槽位 FEET。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:347

详细生效链路

  1. 注册 ATTRIBUTESAttributes.WATER_MOVEMENT_EFFICIENCY,每级 +0.33333334F
  2. 装备时通过 ItemStack#forEachModifierEnchantmentHelper#forEachModifier 合并到实体属性。
  3. 水中移动逻辑读取 Attributes.WATER_MOVEMENT_EFFICIENCY,关键位置 LivingEntity.java:3010
  4. 该附魔与冰霜行者在 BOOTS_EXCLUSIVE 标签中互斥,附魔选择与铁砧合并都受 Enchantment.areCompatible 约束。
  5. 最终效果是减轻水中水平移动惩罚,提高行走速度。

关键代码展示(逐行注释)

// net/minecraft/world/entity/LivingEntity.java:3007
protected void travelInWater(Vec3 input, double baseGravity, boolean isFalling, double oldY) { // 水中移动的核心逻辑
float slowDown = this.isSprinting() ? 0.9F : this.getWaterSlowDown(); // 先取默认水中减速
float speed = 0.02F; // 默认水中基础移动速度
float waterWalker = (float)this.getAttributeValue(Attributes.WATER_MOVEMENT_EFFICIENCY); // 读取深海探索者对应的属性值
if (!this.onGround()) { // 悬空游动时
waterWalker *= 0.5F; // 附魔效果减半
}

if (waterWalker > 0.0F) { // 只有带加成时才调整
slowDown += (0.54600006F - slowDown) * waterWalker; // 把减速系数往更好的值拉近
speed += (this.getSpeed() - speed) * waterWalker; // 同时提高真实移动速度
}

this.moveRelative(speed, input); // 按新的速度应用输入向量
this.move(MoverType.SELF, this.getDeltaMovement()); // 推进实体实际位移
}

完整注册源码

      register(// 353
context,
DEPTH_STRIDER,
Enchantment.enchantment(// 356
Enchantment.definition(// 357
items.getOrThrow(ItemTags.FOOT_ARMOR_ENCHANTABLE),// 358
2,
3,
Enchantment.dynamicCost(10, 10),// 361
Enchantment.dynamicCost(25, 10),// 362
4,
EquipmentSlotGroup.FEET
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.BOOTS_EXCLUSIVE))// 367
.withEffect(// 368
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.depth_strider"),// 371
Attributes.WATER_MOVEMENT_EFFICIENCY,
LevelBasedValue.perLevel(0.33333334F),// 373
AttributeModifier.Operation.ADD_VALUE
)
)
);

6.10 冰霜行者 frost_walker

  • 中文名:冰霜行者
  • 命名空间 ID:frost_walker
  • 最高等级:II
  • 描述:在水面行走时产生霜冰,并免疫踩踏燃烧伤害。
  • 适用物品:脚部盔甲;ItemTags.FOOT_ARMOR_ENCHANTABLE,槽位 FEET。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:372

详细生效链路

  1. 注册 DAMAGE_IMMUNITY,匹配 DamageTypeTags.BURN_FROM_STEPPING,用于免疫岩浆块/营火等踩踏伤害。
  2. 实体判定是否对伤害无敌时,LivingEntity#isInvulnerableTo 调用 EnchantmentHelper#isImmuneToDamage
  3. 同时注册 LOCATION_CHANGED;当实体在地面行走且不骑乘时,LivingEntity#onChangedBlock 会调用 EnchantmentHelper#runLocationChangedEffects
  4. Enchantment#runLocationChangedEffects 维护激活状态并在条件满足时执行 ReplaceDisk
  5. ReplaceDisk#apply 以实体位置为中心把脚下符合条件的水替换成霜冰,这就是水面冻结的实际落点。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/effects/ReplaceDisk.java:42
public void apply(ServerLevel serverLevel, int enchantmentLevel, EnchantedItemInUse item, Entity entity, Vec3 position) { // 冰霜行者最终的“改方块”执行器
BlockPos centerBlock = BlockPos.containing(position).offset(this.offset); // 先求出以实体脚下为中心的替换圆盘中心
RandomSource random = entity.getRandom(); // 取实体随机源
int dist = (int)this.radius.calculate(enchantmentLevel); // 按附魔等级算圆盘半径
int height = (int)this.height.calculate(enchantmentLevel); // 按配置算圆盘高度

for (BlockPos pos : BlockPos.betweenClosed(centerBlock.offset(-dist, 0, -dist), centerBlock.offset(dist, Math.min(height - 1, 0), dist))) { // 枚举圆盘包围盒内所有方块
if (pos.distToCenterSqr(position.x(), pos.getY() + 0.5, position.z()) < Mth.square(dist) // 先要求该方块仍在圆形范围内
&& this.predicate.map(p -> p.test(serverLevel, pos)).orElse(true) // 再要求满足“上方空气、当前位置是水、无遮挡”等谓词
&& CraftEventFactory.handleBlockFormEvent(serverLevel, pos, this.blockState.getState(serverLevel, random, pos), 3, entity, true)) { // 最后尝试把该位置替换成霜冰
this.triggerGameEvent.ifPresent(event -> serverLevel.gameEvent(entity, (Holder<GameEvent>)event, pos)); // 成功替换后发出方块放置事件
}
}
}

完整注册源码

      register(// 378
context,
FROST_WALKER,
Enchantment.enchantment(// 381
Enchantment.definition(// 382
items.getOrThrow(ItemTags.FOOT_ARMOR_ENCHANTABLE),// 383
2,
2,
Enchantment.dynamicCost(10, 10),// 386
Enchantment.dynamicCost(25, 10),// 387
4,
EquipmentSlotGroup.FEET
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.BOOTS_EXCLUSIVE))// 392
.withEffect(// 393
EnchantmentEffectComponents.DAMAGE_IMMUNITY,
DamageImmunity.INSTANCE,
DamageSourceCondition.hasDamageSource(// 396
DamageSourcePredicate.Builder.damageType()// 397
.tag(TagPredicate.is(DamageTypeTags.BURN_FROM_STEPPING))// 398
.tag(TagPredicate.isNot(DamageTypeTags.BYPASSES_INVULNERABILITY))// 399
)
)
.withEffect(// 402
EnchantmentEffectComponents.LOCATION_CHANGED,
new ReplaceDisk(
new LevelBasedValue.Clamped(LevelBasedValue.perLevel(3.0F, 1.0F), 0.0F, 16.0F),// 405
LevelBasedValue.constant(1.0F),// 406
new Vec3i(0, -1, 0),
Optional.of(// 408
BlockPredicate.allOf(// 409
BlockPredicate.matchesTag(new Vec3i(0, 1, 0), BlockTags.AIR),// 410
BlockPredicate.matchesBlocks(Blocks.WATER),// 411
BlockPredicate.matchesFluids(Fluids.WATER),// 412
BlockPredicate.unobstructed()// 413
)
),
BlockStateProvider.simple(Blocks.FROSTED_ICE),// 416
Optional.of(GameEvent.BLOCK_PLACE)// 417
),
AllOfCondition.allOf(// 419
LootItemEntityPropertyCondition.hasProperties(// 420
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().flags(EntityFlagsPredicate.Builder.flags().setOnGround(true))// 421
),
InvertedLootItemCondition.invert(// 423
LootItemEntityPropertyCondition.hasProperties(// 424
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().vehicle(EntityPredicate.Builder.entity())// 425
)
)
)
)
);

7.1 绑定诅咒 binding_curse

  • 中文名:绑定诅咒
  • 命名空间 ID:binding_curse
  • 最高等级:I
  • 描述:受影响物品在装备时不能被卸下,创造模式不受影响。
  • 适用物品:可装备物品;ItemTags.EQUIPPABLE_ENCHANTABLE,槽位 ARMOR。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:425

详细生效链路

  1. 注册时不写数值效果,只写入特殊组件 PREVENT_ARMOR_CHANGE
  2. 玩家尝试把手中物品与装备槽互换时,Equippable#swapWithEquipmentSlot 会检查当前装备。
  3. 若当前装备存在 PREVENT_ARMOR_CHANGE 且玩家不是创造模式,则交换被拒绝。
  4. 其他生物尝试替换装备时也会通过 EnchantmentHelper.has(item, PREVENT_ARMOR_CHANGE) 进行保护判断。
  5. 它属于 CURSE 标签,所以砂轮不会把它去掉。

关键代码展示(逐行注释)

// net/minecraft/world/item/equipment/Equippable.java:130
public InteractionResult swapWithEquipmentSlot(ItemStack inHand, Player player) { // 玩家右键穿脱装备时会走这个方法
if (player.canUseSlot(this.slot) && this.canBeEquippedBy(player.typeHolder())) { // 先确认槽位与物品类型合法
ItemStack inEquipmentSlot = player.getItemBySlot(this.slot); // 取出当前已经穿在身上的装备
if ((!EnchantmentHelper.has(inEquipmentSlot, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE) || player.isCreative()) // 如果当前装备没有绑定诅咒,或者玩家处于创造模式
&& !ItemStack.isSameItemSameComponents(inHand, inEquipmentSlot)) { // 并且手里和身上不是完全相同的物品
// 下面才允许继续正常交换装备
} else { // 否则
return InteractionResult.FAIL; // 直接拒绝脱下/替换
}
} else {
return InteractionResult.PASS; // 不适用则交给其他逻辑
}
}

完整注册源码

      register(// 431
context,
BINDING_CURSE,
Enchantment.enchantment(// 434
Enchantment.definition(// 435
items.getOrThrow(ItemTags.EQUIPPABLE_ENCHANTABLE),// 436
1,
1,
Enchantment.constantCost(25),// 439
Enchantment.constantCost(50),// 440
8,
EquipmentSlotGroup.ARMOR
)
)
.withEffect(EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE)// 445
);

7.2 灵魂疾行 soul_speed

  • 中文名:灵魂疾行
  • 命名空间 ID:soul_speed
  • 最高等级:III
  • 描述:增加玩家在灵魂沙和灵魂土上的移动速度。
  • 适用物品:脚部盔甲;ItemTags.FOOT_ARMOR_ENCHANTABLE,槽位 FEET。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:489

详细生效链路

  1. 注册 LOCATION_CHANGED,实体站在灵魂疾行方块上移动时激活。
  2. 激活后用 EnchantmentAttributeEffect 临时添加 MOVEMENT_SPEEDMOVEMENT_EFFICIENCY
  3. 当条件不再满足时,Enchantment#runLocationChangedEffectsonDeactivated 把临时属性移除。
  4. 另一个 LOCATION_CHANGED 效果带随机概率,会执行 ChangeItemDamage(1),因此靴子会磨损。
  5. 此外还有两个 TICK 效果:一个生成灵魂粒子,一个播放 SOUL_ESCAPE 音效。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/EnchantmentHelper.java:254
public static void runLocationChangedEffects(ServerLevel serverLevel, LivingEntity entity) { // 实体位置变化时统一分发 LOCATION_CHANGED
runIterationOnEquipment(entity, (enchantment, level, item) -> enchantment.value().runLocationChangedEffects(serverLevel, level, item, entity)); // 遍历全身装备,让灵魂疾行这类附魔检查是否激活
}

// net/minecraft/world/item/enchantment/EnchantmentHelper.java:270
public static void tickEffects(ServerLevel serverLevel, LivingEntity entity) { // 每 tick 统一分发 TICK 组件
runIterationOnEquipment(entity, (enchantment, level, item) -> enchantment.value().tick(serverLevel, level, item, entity)); // 灵魂粒子与音效就在这里持续触发
}

完整注册源码

      register(// 496
context,
SOUL_SPEED,
Enchantment.enchantment(// 499
Enchantment.definition(// 500
items.getOrThrow(ItemTags.FOOT_ARMOR_ENCHANTABLE),// 501
1,
3,
Enchantment.dynamicCost(10, 10),// 504
Enchantment.dynamicCost(25, 10),// 505
8,
EquipmentSlotGroup.FEET
)
)
.withEffect(// 510
EnchantmentEffectComponents.LOCATION_CHANGED,
AllOf.locationBasedEffects(// 512
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.soul_speed"),// 514
Attributes.MOVEMENT_SPEED,
LevelBasedValue.perLevel(0.0405F, 0.0105F),// 516
AttributeModifier.Operation.ADD_VALUE
),
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.soul_speed"),// 520
Attributes.MOVEMENT_EFFICIENCY,
LevelBasedValue.constant(1.0F),// 522
AttributeModifier.Operation.ADD_VALUE
)
),
soulSpeedMovementCondition
)
.withEffect(// 528
EnchantmentEffectComponents.LOCATION_CHANGED,
new ChangeItemDamage(LevelBasedValue.constant(1.0F)),// 530
AllOfCondition.allOf(// 531
LootItemRandomChanceCondition.randomChance(EnchantmentLevelProvider.forEnchantmentLevel(LevelBasedValue.constant(0.04F))),// 532
LootItemEntityPropertyCondition.hasProperties(// 533
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity()// 535
.flags(EntityFlagsPredicate.Builder.flags().setOnGround(true))// 536
.movementAffectedBy(// 537
LocationPredicate.Builder.location()// 538
.setBlock(net.minecraft.advancements.criterion.BlockPredicate.Builder.block().of(blocks, BlockTags.SOUL_SPEED_BLOCKS))// 539
)
)
)
)
.withEffect(// 544
EnchantmentEffectComponents.TICK,
new SpawnParticlesEffect(
ParticleTypes.SOUL,
SpawnParticlesEffect.inBoundingBox(),// 548
SpawnParticlesEffect.offsetFromEntityPosition(0.1F),// 549
SpawnParticlesEffect.movementScaled(-0.2F),// 550
SpawnParticlesEffect.fixedVelocity(ConstantFloat.of(0.1F)),// 551
ConstantFloat.of(1.0F)// 552
),
LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, soulSpeedEffectCondition)// 554
)
.withEffect(// 556
EnchantmentEffectComponents.TICK,
new PlaySoundEffect(List.of(SoundEvents.SOUL_ESCAPE), ConstantFloat.of(0.6F), UniformFloat.of(0.6F, 1.0F)),// 558
AllOfCondition.allOf(// 559
LootItemRandomChanceCondition.randomChance(0.35F),// 560
LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, soulSpeedEffectCondition)// 561
)
)
);

7.3 迅捷潜行 swift_sneak

  • 中文名:迅捷潜行
  • 命名空间 ID:swift_sneak
  • 最高等级:III
  • 描述:提高玩家潜行、爬行时的移动速度。
  • 适用物品:腿部盔甲;ItemTags.LEG_ARMOR_ENCHANTABLE,槽位 LEGS。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:558

详细生效链路

  1. 注册 ATTRIBUTESAttributes.SNEAKING_SPEED,每级 +0.15F
  2. 装备时 ItemStack#forEachModifier 会向实体属性系统追加附魔提供的 AttributeModifier
  3. EnchantmentHelper#forEachModifier 根据装备槽位筛出匹配的附魔属性效果。
  4. 玩家潜行和爬行移动速度逻辑读取 SNEAKING_SPEED 属性。
  5. 因此迅捷潜行是长期属性型附魔,没有额外 post-attack 或 tick 分支。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/Enchantments.java:579
.withEffect( // 给迅捷潜行注册真正的运行时效果
EnchantmentEffectComponents.ATTRIBUTES, // 该附魔通过属性系统生效
new EnchantmentAttributeEffect( // 创建一个附魔属性修饰器
Identifier.withDefaultNamespace("enchantment.swift_sneak"), // 该修饰器的唯一标识
Attributes.SNEAKING_SPEED, // 修改的是“潜行速度”属性
LevelBasedValue.perLevel(0.15F), // 每级增加 0.15
AttributeModifier.Operation.ADD_VALUE // 直接相加
)
)

完整注册源码

      register(// 565
context,
SWIFT_SNEAK,
Enchantment.enchantment(// 568
Enchantment.definition(// 569
items.getOrThrow(ItemTags.LEG_ARMOR_ENCHANTABLE),// 570
1,
3,
Enchantment.dynamicCost(25, 25),// 573
Enchantment.dynamicCost(75, 25),// 574
8,
EquipmentSlotGroup.LEGS
)
)
.withEffect(// 579
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.swift_sneak"),// 582
Attributes.SNEAKING_SPEED,
LevelBasedValue.perLevel(0.15F),// 584
AttributeModifier.Operation.ADD_VALUE
)
)
);

7.4 锋利 sharpness

  • 中文名:锋利
  • 命名空间 ID:sharpness
  • 最高等级:V
  • 描述:增加近战攻击伤害。
  • 适用物品:锐利武器/近战武器;supported 为 SHARP_WEAPON_ENCHANTABLE,primary 为 MELEE_WEAPON_ENCHANTABLE,槽位 MAINHAND。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:582

详细生效链路

  1. 注册 DAMAGE,数值为 AddValue(LevelBasedValue.perLevel(1.0F, 0.5F))
  2. 玩家近战时 ServerPlayer#getEnchantedDamageEnchantmentHelper#modifyDamage;普通生物近战时 Mob#doHurtTarget 也调同一个 helper。
  3. helper 遍历武器附魔并调用 Enchantment#modifyDamage
  4. modifyDamage 最终走 modifyDamageFilteredValue(DAMAGE, ...),把锋利的增伤叠加到基础伤害。
  5. 锋利与亡灵杀手、节肢杀手、穿刺、致密、破甲同在 DAMAGE_EXCLUSIVE 中互斥。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/EnchantmentHelper.java:178
public static float modifyDamage(ServerLevel serverLevel, ItemStack itemStack, Entity victim, DamageSource damageSource, float damage) { // 武器增伤总入口
MutableFloat result = new MutableFloat(damage); // 先把基础伤害放进可变容器
runIterationOnItem(itemStack, (enchantment, level) -> enchantment.value().modifyDamage(serverLevel, level, itemStack, victim, damageSource, result)); // 逐个让武器附魔改写伤害
return result.floatValue(); // 返回叠加后的最终伤害
}

完整注册源码

      register(// 589
context,
SHARPNESS,
Enchantment.enchantment(// 592
Enchantment.definition(// 593
items.getOrThrow(ItemTags.SHARP_WEAPON_ENCHANTABLE),// 594
items.getOrThrow(ItemTags.MELEE_WEAPON_ENCHANTABLE),// 595
10,
5,
Enchantment.dynamicCost(1, 11),// 598
Enchantment.dynamicCost(21, 11),// 599
1,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.DAMAGE_EXCLUSIVE))// 604
.withEffect(EnchantmentEffectComponents.DAMAGE, new AddValue(LevelBasedValue.perLevel(1.0F, 0.5F)))// 605
);

7.5 亡灵杀手 smite

  • 中文名:亡灵杀手
  • 命名空间 ID:smite
  • 最高等级:V
  • 描述:对亡灵生物造成额外伤害。
  • 适用物品:武器/近战武器;supported 为 WEAPON_ENCHANTABLE,primary 为 MELEE_WEAPON_ENCHANTABLE,槽位 MAINHAND。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:600

详细生效链路

  1. 注册 DAMAGE,每级 +2.5F
  2. 该效果带实体条件:目标必须属于 EntityTypeTags.SENSITIVE_TO_SMITE
  3. 玩家或生物攻击时都通过 EnchantmentHelper#modifyDamage 进入统一增伤链。
  4. Enchantment#modifyDamageFilteredValueENCHANTED_DAMAGE 上下文校验目标类型是否匹配。
  5. 只有亡灵类目标满足条件时才会追加伤害。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/Enchantments.java:623
.withEffect( // 给亡灵杀手挂伤害效果
EnchantmentEffectComponents.DAMAGE, // 作用组件是“直接改伤害”
new AddValue(LevelBasedValue.perLevel(2.5F)), // 每级额外 +2.5 伤害
LootItemEntityPropertyCondition.hasProperties( // 只有满足实体条件时才加伤
LootContext.EntityTarget.THIS, // 检查的是当前受害者
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(entityTypes, EntityTypeTags.SENSITIVE_TO_SMITE)) // 目标必须属于亡灵敏感标签
)
)

完整注册源码

      register(// 607
context,
SMITE,
Enchantment.enchantment(// 610
Enchantment.definition(// 611
items.getOrThrow(ItemTags.WEAPON_ENCHANTABLE),// 612
items.getOrThrow(ItemTags.MELEE_WEAPON_ENCHANTABLE),// 613
5,
5,
Enchantment.dynamicCost(5, 8),// 616
Enchantment.dynamicCost(25, 8),// 617
2,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.DAMAGE_EXCLUSIVE))// 622
.withEffect(// 623
EnchantmentEffectComponents.DAMAGE,
new AddValue(LevelBasedValue.perLevel(2.5F)),// 625
LootItemEntityPropertyCondition.hasProperties(// 626
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(entityTypes, EntityTypeTags.SENSITIVE_TO_SMITE))// 628
)
)
);

7.6 节肢杀手 bane_of_arthropods

  • 中文名:节肢杀手
  • 命名空间 ID:bane_of_arthropods
  • 最高等级:V
  • 描述:对节肢生物造成额外伤害并附加缓慢效果。
  • 适用物品:武器/近战武器;supported 为 WEAPON_ENCHANTABLE,primary 为 MELEE_WEAPON_ENCHANTABLE,槽位 MAINHAND。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:625

详细生效链路

  1. 第一条链是 DAMAGE:对 EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS 每级 +2.5F
  2. 第二条链是 POST_ATTACK:攻击成功后,如果伤害是 direct 且目标仍是节肢目标,则触发附加效果。
  3. 攻击后的附魔效果由 EnchantmentHelper#doPostAttackEffects 分发到 Enchantment#doPostAttack
  4. 执行器 ApplyMobEffect 会随机时长/倍率地给目标附加 MobEffects.SLOWNESS
  5. 因此额外伤害和缓慢效果分别落在 modifyDamagedoPostAttackEffects 两条链路上。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/Enchantment.java:286
public static void doPostAttack( // 单条 POST_ATTACK 效果真正执行的位置
TargetedConditionalEffect<EnchantmentEntityEffect> effect,
ServerLevel serverLevel,
int enchantmentLevel,
EnchantedItemInUse item,
Entity victim,
DamageSource damageSource
) {
if (effect.matches(damageContext(serverLevel, enchantmentLevel, victim, damageSource))) { // 先校验伤害条件是否满足
Entity target = switch (effect.affected()) { // 决定效果要作用到谁身上
case ATTACKER -> damageSource.getEntity(); // 作用攻击者
case DAMAGING_ENTITY -> damageSource.getDirectEntity(); // 作用直接伤害实体
case VICTIM -> victim; // 作用受害者
};
if (target != null) { // 目标存在时
effect.effect().apply(serverLevel, enchantmentLevel, item, target, target.position()); // 真正执行缓慢、点燃、爆炸等效果
}
}
}

完整注册源码

      register(// 632
context,
BANE_OF_ARTHROPODS,
Enchantment.enchantment(// 635
Enchantment.definition(// 636
items.getOrThrow(ItemTags.WEAPON_ENCHANTABLE),// 637
items.getOrThrow(ItemTags.MELEE_WEAPON_ENCHANTABLE),// 638
5,
5,
Enchantment.dynamicCost(5, 8),// 641
Enchantment.dynamicCost(25, 8),// 642
2,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.DAMAGE_EXCLUSIVE))// 647
.withEffect(// 648
EnchantmentEffectComponents.DAMAGE,
new AddValue(LevelBasedValue.perLevel(2.5F)),// 650
LootItemEntityPropertyCondition.hasProperties(// 651
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(entityTypes, EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS))// 653
)
)
.withEffect(// 656
EnchantmentEffectComponents.POST_ATTACK,
EnchantmentTarget.ATTACKER,
EnchantmentTarget.VICTIM,
new ApplyMobEffect(
HolderSet.direct(MobEffects.SLOWNESS),// 661
LevelBasedValue.constant(1.5F),// 662
LevelBasedValue.perLevel(1.5F, 0.5F),// 663
LevelBasedValue.constant(3.0F),// 664
LevelBasedValue.constant(3.0F)// 665
),
LootItemEntityPropertyCondition.hasProperties(// 667
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(entityTypes, EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS))// 669
)
.and(DamageSourceCondition.hasDamageSource(DamageSourcePredicate.Builder.damageType().isDirect(true)))// 671
)
);

7.7 击退 knockback

  • 中文名:击退
  • 命名空间 ID:knockback
  • 最高等级:II
  • 描述:增加近战攻击造成的击退距离。
  • 适用物品:近战武器;ItemTags.MELEE_WEAPON_ENCHANTABLE,槽位 MAINHAND。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:667

详细生效链路

  1. 注册 KNOCKBACK,每级 AddValue(1.0F)
  2. 近战攻击计算击退时,LivingEntity#getKnockbackEnchantmentHelper#modifyKnockback
  3. helper 遍历武器附魔,Enchantment#modifyKnockback 读取 KNOCKBACK 组件并修改值。
  4. 返回的击退值继续传入 causeExtraKnockback
  5. 所以该附魔只影响近战击退距离,不改变直接伤害数值。

关键代码展示(逐行注释)

// net/minecraft/world/entity/LivingEntity.java:1906
protected float getKnockback(Entity target, DamageSource damageSource) { // 近战命中后计算额外击退
float knockback = (float)this.getAttributeValue(Attributes.ATTACK_KNOCKBACK); // 先读实体原本的攻击击退属性
return this.level() instanceof ServerLevel level // 仅服务端做附魔修正
? EnchantmentHelper.modifyKnockback(level, this.getWeaponItem(), target, damageSource, knockback) / 2.0F // 让击退附魔修改数值后再折半作为实际击退
: knockback / 2.0F; // 客户端仅走基础值
}

完整注册源码

      register(// 674
context,
KNOCKBACK,
Enchantment.enchantment(// 677
Enchantment.definition(// 678
items.getOrThrow(ItemTags.MELEE_WEAPON_ENCHANTABLE),// 679
5,
2,
Enchantment.dynamicCost(5, 20),// 682
Enchantment.dynamicCost(55, 20),// 683
2,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(EnchantmentEffectComponents.KNOCKBACK, new AddValue(LevelBasedValue.perLevel(1.0F)))// 688
);

7.8 火焰附加 fire_aspect

  • 中文名:火焰附加
  • 命名空间 ID:fire_aspect
  • 最高等级:II
  • 描述:使被近战攻击目标着火。
  • 适用物品:可火焰附加武器/近战武器;supported 为 FIRE_ASPECT_ENCHANTABLE,primary 为 MELEE_WEAPON_ENCHANTABLE,槽位 MAINHAND。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:683

详细生效链路

  1. 注册 POST_ATTACK,enchanted=ATTACKER,affected=VICTIM,执行器为 Ignite
  2. 攻击成功后,玩家 itemAttackInteraction 或生物 Mob#doHurtTarget 会调用 EnchantmentHelper#doPostAttackEffects
  3. 条件要求 DamageSource 为直接伤害。
  4. Ignite#apply 会先触发 Bukkit combust 事件,未取消时调用 Entity#igniteForSeconds 让目标着火。
  5. 同时它还被放进 SMELTS_LOOT 标签,因此相关实体掉落可经战利品条件变成熟制掉落。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/effects/Ignite.java:20
public void apply(ServerLevel serverLevel, int enchantmentLevel, EnchantedItemInUse item, Entity entity, Vec3 position) { // 火焰附加最终执行器
EntityCombustEvent entityCombustEvent; // 先准备燃烧事件对象
if (item.owner() != null) { // 如果能拿到攻击者
entityCombustEvent = new EntityCombustByEntityEvent( // 构造“由实体点燃”的事件
item.owner().getBukkitEntity(), entity.getBukkitEntity(), this.duration.calculate(enchantmentLevel) // 燃烧时长按附魔等级计算
);
} else { // 没有攻击者时
entityCombustEvent = new EntityCombustEvent(entity.getBukkitEntity(), this.duration.calculate(enchantmentLevel)); // 构造普通燃烧事件
}

Bukkit.getPluginManager().callEvent(entityCombustEvent); // 先把事件抛给插件层
if (!entityCombustEvent.isCancelled()) { // 没被取消时
entity.igniteForSeconds(entityCombustEvent.getDuration(), false); // 才真正让目标着火
}
}

完整注册源码

      register(// 690
context,
FIRE_ASPECT,
Enchantment.enchantment(// 693
Enchantment.definition(// 694
items.getOrThrow(ItemTags.FIRE_ASPECT_ENCHANTABLE),// 695
items.getOrThrow(ItemTags.MELEE_WEAPON_ENCHANTABLE),// 696
2,
2,
Enchantment.dynamicCost(10, 20),// 699
Enchantment.dynamicCost(60, 20),// 700
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 705
EnchantmentEffectComponents.POST_ATTACK,
EnchantmentTarget.ATTACKER,
EnchantmentTarget.VICTIM,
new Ignite(LevelBasedValue.perLevel(4.0F)),// 709
DamageSourceCondition.hasDamageSource(DamageSourcePredicate.Builder.damageType().isDirect(true))// 710
)
);

7.9 抢夺 looting

  • 中文名:抢夺
  • 命名空间 ID:looting
  • 最高等级:III
  • 描述:增加生物掉落物的数量或概率。
  • 适用物品:近战武器;ItemTags.MELEE_WEAPON_ENCHANTABLE,槽位 MAINHAND。
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:706

详细生效链路

  1. 注册 EQUIPMENT_DROPS,攻击者为玩家时对受害者装备掉落概率每级 +0.01F
  2. 生物死亡掉装备时 Mob#dropCustomDeathLootEnchantmentHelper#processEquipmentDropChance
  3. 该 helper 会分别遍历死者与攻击者装备,按 TargetedConditionalEffect 规则修改装备掉落概率。
  4. 普通实体战利品数量/概率则由 loot function EnchantedCountIncreaseFunctionLootItemRandomChanceWithEnchantedBonusCondition 读取抢夺等级。
  5. 所以抢夺同时影响装备掉落和战利品表数量,是组件链和战利品旁路并存的附魔。

关键代码展示(逐行注释)

// net/minecraft/world/entity/Mob.java:1050
protected void dropCustomDeathLoot(ServerLevel level, DamageSource source, boolean killedByPlayer) { // 生物死亡后掉装备的主入口
super.dropCustomDeathLoot(level, source, killedByPlayer); // 先执行父类逻辑

for (EquipmentSlot slot : EquipmentSlot.VALUES) { // 逐个遍历所有装备槽
if (!this.shouldSkipLoot(slot)) { // 跳过不允许掉落的槽位
ItemStack itemStack = this.getItemBySlot(slot); // 取出该槽位装备
float dropChance = this.dropChances.byEquipment(slot); // 读基础掉落概率
if (dropChance != 0.0F) { // 概率不为 0 才继续
if (source.getEntity() instanceof LivingEntity livingSource && this.level() instanceof ServerLevel serverLevel) { // 如果击杀者是活体
dropChance = EnchantmentHelper.processEquipmentDropChance(serverLevel, livingSource, source, dropChance); // 让抢夺等附魔改写装备掉率
}
}
}
}
}

// net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java:71
public ItemStack run(ItemStack itemStack, LootContext context) { // 战利品表里的“按附魔提高数量”函数
Entity killer = context.getOptionalParameter(LootContextParams.ATTACKING_ENTITY); // 取出击杀者
if (killer instanceof LivingEntity entity) { // 只有活体击杀者才有附魔
int level = EnchantmentHelper.getEnchantmentLevel(this.enchantment, entity); // 读取抢夺等级
if (level == 0) { // 没有抢夺时
return itemStack; // 保持原数量
}
}
}

完整注册源码

      register(// 713
context,
LOOTING,
Enchantment.enchantment(// 716
Enchantment.definition(// 717
items.getOrThrow(ItemTags.MELEE_WEAPON_ENCHANTABLE),// 718
2,
3,
Enchantment.dynamicCost(15, 9),// 721
Enchantment.dynamicCost(65, 9),// 722
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 727
EnchantmentEffectComponents.EQUIPMENT_DROPS,
EnchantmentTarget.ATTACKER,
EnchantmentTarget.VICTIM,
new AddValue(LevelBasedValue.perLevel(0.01F)),// 731
LootItemEntityPropertyCondition.hasProperties(// 732
LootContext.EntityTarget.ATTACKER, EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(entityTypes, EntityType.PLAYER))// 733
)
)
);

8.1 横扫之刃 sweeping_edge

  • 中文名:横扫之刃
  • 命名空间 ID:sweeping_edge
  • 最高等级:III
  • 描述:增加横扫攻击伤害。
  • 适用物品:横扫武器;ItemTags.SWEEPING_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:730

详细生效链路

  1. 注册 ATTRIBUTES 组件,为 Attributes.SWEEPING_DAMAGE_RATIO 写入一个随等级增长的分数值。
  2. 该属性修饰符在武器作为主手装备时,经 ItemStack#forEachModifierEnchantmentHelper#forEachModifier 挂到玩家属性集。
  3. 玩家近战命中后,Player#attack 在满足横扫判定时进入 Player#doSweepAttack(Entity,float,DamageSource,float)net/minecraft/world/entity/player/Player.java:1197)。
  4. 该方法在 net/minecraft/world/entity/player/Player.java:1200 读取 Attributes.SWEEPING_DAMAGE_RATIO,计算 1.0F + ratio * baseDamage 作为横扫伤害。
  5. 随后附近实体逐个受到横扫伤害,并继续进入 EnchantmentHelper#doPostAttackEffects,所以横扫之刃只抬高横扫段伤害,不改变主目标直击伤害公式。

关键代码展示(逐行注释)

// net/minecraft/world/entity/player/Player.java:1197
private void doSweepAttack(Entity entity, float baseDamage, DamageSource damageSource, float attackStrengthScale) { // 横扫攻击真正展开的地方
this.playServerSideSound(SoundEvents.PLAYER_ATTACK_SWEEP); // 播放横扫音效
if (this.level() instanceof ServerLevel serverLevel) { // 只在服务端真正结算横扫命中
float var12 = 1.0F + (float)this.getAttributeValue(Attributes.SWEEPING_DAMAGE_RATIO) * baseDamage; // 读取横扫之刃提供的横扫伤害比例

for (LivingEntity nearby : this.level().getEntitiesOfClass(LivingEntity.class, entity.getBoundingBox().inflate(1.0, 0.25, 1.0))) { // 搜索主目标附近的实体
if (nearby != this && nearby != entity && !this.isAlliedTo(nearby) && !(nearby instanceof ArmorStand armorStand && armorStand.isMarker()) && this.distanceToSqr(nearby) < 9.0) { // 过滤无效目标
float enchantedDamage = this.getEnchantedDamage(nearby, var12, damageSource) * attackStrengthScale; // 计算横扫伤害
if (nearby.hurtServer(serverLevel, damageSource.knownCause(DamageCause.ENTITY_SWEEP_ATTACK), enchantedDamage) && !nearby.lastDamageCancelled) { // 对附近目标造成横扫伤害
EnchantmentHelper.doPostAttackEffects(serverLevel, nearby, damageSource); // 横扫命中的实体也会继续触发攻击后附魔
}
}
}
}
}

完整注册源码

      register(// 737
context,
SWEEPING_EDGE,
Enchantment.enchantment(// 740
Enchantment.definition(// 741
items.getOrThrow(ItemTags.SWEEPING_ENCHANTABLE),// 742
2,
3,
Enchantment.dynamicCost(5, 9),// 745
Enchantment.dynamicCost(20, 9),// 746
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 751
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.sweeping_edge"),// 754
Attributes.SWEEPING_DAMAGE_RATIO,
new LevelBasedValue.Fraction(LevelBasedValue.perLevel(1.0F), LevelBasedValue.perLevel(2.0F, 1.0F)),// 756
AttributeModifier.Operation.ADD_VALUE
)
)
);

8.2 效率 efficiency

  • 中文名:效率
  • 命名空间 ID:efficiency
  • 最高等级:V
  • 描述:加快挖掘速度。
  • 适用物品:可挖掘附魔工具;ItemTags.MINING_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:754

详细生效链路

  1. 注册 ATTRIBUTES 组件,对 Attributes.MINING_EFFICIENCY 施加 new LevelBasedValue.LevelsSquared(1.0F),也就是等级平方加成。
  2. 当工具在主手生效时,这个属性修饰符通过附魔属性遍历挂到玩家实体属性上。
  3. 玩家计算挖掘速度时,Player#getDestroySpeednet/minecraft/world/entity/player/Player.java:632this.getAttributeValue(Attributes.MINING_EFFICIENCY) 加到最终速度。
  4. 这个最终速度再参与方块破坏进度计算,因此效率附魔影响的是每 tick 的破坏推进量,而不是掉落结果。
  5. 水下、空中、疲劳等惩罚仍在后续流程照常叠加,所以效率只是把基础挖掘速度抬高。

关键代码展示(逐行注释)

// net/minecraft/world/entity/player/Player.java:629
public float getDestroySpeed(BlockState state) { // 玩家破坏方块时的速度计算入口
float speed = this.inventory.getSelectedItem().getDestroySpeed(state); // 先取工具对该方块的基础速度
if (speed > 1.0F) { // 只有正确工具时效率才有意义
speed += (float)this.getAttributeValue(Attributes.MINING_EFFICIENCY); // 把效率附魔提供的属性直接加上去
}

speed *= (float)this.getAttributeValue(Attributes.BLOCK_BREAK_SPEED); // 再乘通用破坏速度倍率
if (this.isEyeInFluid(FluidTags.WATER)) { // 水下挖掘时
speed *= (float)this.getAttribute(Attributes.SUBMERGED_MINING_SPEED).getValue(); // 继续叠加水下速掘属性
}

if (!this.onGround()) { // 空中挖掘时
speed /= 5.0F; // 额外施加空中惩罚
}
}

完整注册源码

      register(// 761
context,
EFFICIENCY,
Enchantment.enchantment(// 764
Enchantment.definition(// 765
items.getOrThrow(ItemTags.MINING_ENCHANTABLE),// 766
10,
5,
Enchantment.dynamicCost(1, 10),// 769
Enchantment.dynamicCost(51, 10),// 770
1,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 775
EnchantmentEffectComponents.ATTRIBUTES,
new EnchantmentAttributeEffect(
Identifier.withDefaultNamespace("enchantment.efficiency"),// 778
Attributes.MINING_EFFICIENCY,
new LevelBasedValue.LevelsSquared(1.0F),
AttributeModifier.Operation.ADD_VALUE
)
)
);

8.3 精准采集 silk_touch

  • 中文名:精准采集
  • 命名空间 ID:silk_touch
  • 最高等级:I
  • 描述:使部分被开采的方块直接掉落方块自身,并压制对应经验/副作用。
  • 适用物品:采掘掉落工具;ItemTags.MINING_LOOT_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:778

详细生效链路

  1. 注册中唯一直接写入的组件是 BLOCK_EXPERIENCE,用 SetValue(0.0F) 把挖矿经验清零,并与 MINING_EXCLUSIVE(时运)互斥。
  2. 方块掉经验时,Block#popExperience 路径在 net/minecraft/world/level/block/Block.java:660EnchantmentHelper#processBlockExperience,该 helper 会把精准采集的 SetValue 应用到经验值上。
  3. “掉方块本体而不是普通掉落”不是在 Enchantment 子类里硬编码,而是由战利品表生成器完成:BlockLootSubProvider#hasSilkTouchnet/minecraft/data/loot/BlockLootSubProvider.java:87)和 createSilkTouchDispatchTable:147)会根据工具附魔等级切换掉落分支。
  4. 原版具体方块在 VanillaBlockLoot 中大量使用这条分发表,例如 createSingleItemTableWithSilkTouchdropWhenSilkTouchotherWhenSilkTouch(如 net/minecraft/data/loot/packs/VanillaBlockLoot.java:730:1218:1512)。
  5. 除掉落表外,若附魔被打上特定标签,还会阻止额外副作用:蜂巢放蜂 BeehiveBlock.java:107、陶罐碎裂 DecoratedPotBlock.java:191、冰融化 IceBlock.java:52、蠹虫生成 InfestedBlock.java:64

关键代码展示(逐行注释)

// net/minecraft/world/level/block/Block.java:659
protected int tryDropExperience(ServerLevel level, BlockPos pos, ItemStack tool, IntProvider xpRange) { // 方块决定要不要掉经验时会走这里
int experience = EnchantmentHelper.processBlockExperience(level, tool, xpRange.sample(level.getRandom())); // 先让精准采集等附魔改写经验值
return experience > 0 ? experience : 0; // 最终只返回非负经验
}

完整注册源码

      register(// 785
context,
SILK_TOUCH,
Enchantment.enchantment(// 788
Enchantment.definition(// 789
items.getOrThrow(ItemTags.MINING_LOOT_ENCHANTABLE),// 790
1,
1,
Enchantment.constantCost(15),// 793
Enchantment.constantCost(65),// 794
8,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.MINING_EXCLUSIVE))// 799
.withEffect(EnchantmentEffectComponents.BLOCK_EXPERIENCE, new SetValue(LevelBasedValue.constant(0.0F)))// 800
);

8.4 耐久 unbreaking

  • 中文名:耐久
  • 命名空间 ID:unbreaking
  • 最高等级:III
  • 描述:减少触发耐久消耗的概率。
  • 适用物品:可耐久附魔物品;ItemTags.DURABILITY_ENCHANTABLE,槽位 EquipmentSlotGroup.ANY
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:795

详细生效链路

  1. 注册两个 ITEM_DAMAGE 效果:盔甲分支与非盔甲分支分别使用不同的 RemoveBinomial 概率公式。
  2. 任何物品需要扣耐久时,ItemStack#hurtAndBreak 会在 net/minecraft/world/item/ItemStack.java:669 进入 EnchantmentHelper#processDurabilityChange(ServerLevel,ItemStack,int):int
  3. helper 遍历物品附魔,把待扣减的耐久传入 Enchantment#modifyItemDamageRemoveBinomial 会按等级随机移除一部分应扣耐久。
  4. 返回值是“实际要扣的耐久数”,随后 ItemStack 才真正更新 damage value,所以耐久附魔本质上是提前拦截并缩减损耗。
  5. 由于盔甲和工具走的是两套概率参数,所以同等级下盔甲耐久与工具耐久的保值率并不完全相同。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/EnchantmentHelper.java:96
public static int processDurabilityChange(ServerLevel serverLevel, ItemStack itemStack, int amount) { // 统一处理“本次应该扣多少耐久”
MutableFloat modifiedAmount = new MutableFloat(amount); // 先把原始扣耐久数放进可变容器
runIterationOnItem(itemStack, (enchantment, level) -> enchantment.value().modifyDurabilityChange(serverLevel, level, itemStack, modifiedAmount)); // 逐个让附魔改写这个值
return modifiedAmount.intValue(); // 返回最终实际要扣的耐久
}

完整注册源码

      register(// 802
context,
UNBREAKING,
Enchantment.enchantment(// 805
Enchantment.definition(// 806
items.getOrThrow(ItemTags.DURABILITY_ENCHANTABLE),// 807
5,
3,
Enchantment.dynamicCost(5, 8),// 810
Enchantment.dynamicCost(55, 8),// 811
2,
EquipmentSlotGroup.ANY
)
)
.withEffect(// 816
EnchantmentEffectComponents.ITEM_DAMAGE,
new RemoveBinomial(new LevelBasedValue.Fraction(LevelBasedValue.perLevel(2.0F), LevelBasedValue.perLevel(10.0F, 5.0F))),// 818
MatchTool.toolMatches(ItemPredicate.Builder.item().of(items, ItemTags.ARMOR_ENCHANTABLE))// 819
)
.withEffect(// 821
EnchantmentEffectComponents.ITEM_DAMAGE,
new RemoveBinomial(new LevelBasedValue.Fraction(LevelBasedValue.perLevel(1.0F), LevelBasedValue.perLevel(2.0F, 1.0F))),// 823
InvertedLootItemCondition.invert(MatchTool.toolMatches(ItemPredicate.Builder.item().of(items, ItemTags.ARMOR_ENCHANTABLE)))// 824
)
);

8.5 时运 fortune

  • 中文名:时运
  • 命名空间 ID:fortune
  • 最高等级:III
  • 描述:增加方块掉落物的数量或概率。
  • 适用物品:采掘掉落工具;ItemTags.MINING_LOOT_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:820

详细生效链路

  1. 注册块本身没有 effects 组件,只声明了与精准采集互斥;因此时运主要通过战利品系统旁路生效。
  2. 方块掉落构建 LootContext 时会把工具放进 LootContextParams.TOOL,随后 ApplyBonusCount#runnet/minecraft/world/level/storage/loot/functions/ApplyBonusCount.java:63 读取工具上的时运等级。
  3. 读取点在 ApplyBonusCount.java:66,然后根据不同公式执行 ore_dropsuniform_bonus_countbinomial_with_bonus_count 计算新掉落数量。
  4. 若掉落表需要“随时运提升触发概率”而不是直接增量,则 BonusLevelTableCondition#testnet/minecraft/world/level/storage/loot/predicates/BonusLevelTableCondition.java:37 读取同一个附魔等级决定概率。
  5. 原版方块掉落生成器 VanillaBlockLoot / BlockLootSubProvider 把这些函数和条件绑定到矿石、树叶、作物等掉落表,所以时运的真正生效点分散在具体方块的 loot 规则上。

关键代码展示(逐行注释)

// net/minecraft/world/level/storage/loot/functions/ApplyBonusCount.java:63
public ItemStack run(ItemStack itemStack, LootContext context) { // 时运最常见的掉落数量修正函数
ItemInstance tool = context.getOptionalParameter(LootContextParams.TOOL); // 取出本次挖掘使用的工具
if (tool != null) { // 工具存在时
int level = EnchantmentHelper.getItemEnchantmentLevel(this.enchantment, tool); // 读取工具上的时运等级
int newCount = this.formula.calculateNewCount(context.getRandom(), itemStack.getCount(), level); // 按配置公式计算新掉落数量
itemStack.setCount(newCount); // 把结果写回掉落堆
}
}

完整注册源码

      register(// 827
context,
FORTUNE,
Enchantment.enchantment(// 830
Enchantment.definition(// 831
items.getOrThrow(ItemTags.MINING_LOOT_ENCHANTABLE),// 832
2,
3,
Enchantment.dynamicCost(15, 9),// 835
Enchantment.dynamicCost(65, 9),// 836
4,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.MINING_EXCLUSIVE))// 841
);

8.6 力量 power

  • 中文名:力量
  • 命名空间 ID:power
  • 最高等级:V
  • 描述:增加箭伤害。
  • 适用物品:弓;ItemTags.BOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:836

详细生效链路

  1. 注册 DAMAGE 组件,条件要求 LootContext.EntityTarget.DIRECT_ATTACKEREntityTypeTags.ARROWS,数值为每级 +1.0F,首级起始偏置为 0.5F
  2. 弓或弩射出的箭命中实体时,AbstractArrow#onHitEntitynet/minecraft/world/entity/projectile/arrow/AbstractArrow.java:467EnchantmentHelper#modifyDamage(serverLevel,this.getWeaponItem(),entity,damageSource,arrowDamage)
  3. helper 遍历发射武器上的附魔,再由 Enchantment#modifyDamage 检查 DIRECT_ATTACKER 是否为箭实体;力量满足条件时把伤害加到 MutableFloat
  4. 返回的 arrowDamage 会继续走 entity.hurtOrSimulate(...),因此力量直接改的是箭实体的命中伤害,而不是发射时的初速度。
  5. 因为条件看的是直接攻击者是否为箭,所以该效果能覆盖普通箭、药箭、光灵箭等箭实体,只要发射武器本身带有力量附魔。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:461
Entity entity = hitResult.getEntity(); // 取出箭当前命中的目标
double arrowDamage = this.baseDamage; // 从箭自身基础伤害开始
Entity currentOwner = this.getOwner(); // 取出射手
DamageSource damageSource = this.damageSources().arrow(this, (Entity)(currentOwner != null ? currentOwner : this)); // 构造箭伤害来源
if (this.getWeaponItem() != null && this.level() instanceof ServerLevel serverLevel) { // 如果箭知道自己是哪把武器射出来的
arrowDamage = EnchantmentHelper.modifyDamage(serverLevel, this.getWeaponItem(), entity, damageSource, (float)arrowDamage); // 让力量等武器附魔改写箭伤害
}
int damage = Mth.ceil(Mth.clamp(pow * arrowDamage, 0.0, 2.147483647E9)); // 再按飞行速度换算成最终命中伤害

完整注册源码

      register(// 843
context,
POWER,
Enchantment.enchantment(// 846
Enchantment.definition(// 847
items.getOrThrow(ItemTags.BOW_ENCHANTABLE),// 848
10,
5,
Enchantment.dynamicCost(1, 10),// 851
Enchantment.dynamicCost(16, 10),// 852
1,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 857
EnchantmentEffectComponents.DAMAGE,
new AddValue(LevelBasedValue.perLevel(1.0F, 0.5F)),// 859
LootItemEntityPropertyCondition.hasProperties(// 860
LootContext.EntityTarget.DIRECT_ATTACKER, EntityPredicate.Builder.entity().of(entityTypes, EntityTypeTags.ARROWS).build()// 861
)
)
);

8.7 冲击 punch

  • 中文名:冲击
  • 命名空间 ID:punch
  • 最高等级:II
  • 描述:增加箭的击退距离。
  • 适用物品:弓;ItemTags.BOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:858

详细生效链路

  1. 注册 KNOCKBACK 组件,条件同样要求 DIRECT_ATTACKER 是箭实体,每级 AddValue(1.0F)
  2. 箭命中活体后,AbstractArrow#doKnockback 会在 net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:563EnchantmentHelper#modifyKnockback
  3. helper 遍历发射武器附魔,Enchantment#modifyKnockback 命中 PUNCH 后把击退值累计到结果里。
  4. 最终修改后的击退量被用来推动目标,因此冲击只改变位移,不改变箭本身造成的生命值伤害。
  5. 与力量一样,它依赖的是“箭命中时回查发射武器附魔”,所以效果落点在命中阶段而不是发射阶段。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:561
protected void doKnockback(LivingEntity mob, DamageSource damageSource) { // 箭命中活体后的击退处理
double knockback = this.firedFromWeapon != null && this.level() instanceof ServerLevel serverLevel // 只有知道发射武器时才能读取冲击附魔
? EnchantmentHelper.modifyKnockback(serverLevel, this.firedFromWeapon, mob, damageSource, 0.0F) // 让弓上的冲击附魔改写击退值
: 0.0F; // 否则没有额外击退
if (knockback > 0.0) { // 真有击退时
double knockbackResistance = Math.max(0.0, 1.0 - mob.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); // 扣除目标的击退抗性
Vec3 movement = this.getDeltaMovement().multiply(1.0, 0.0, 1.0).normalize().scale(knockback * 0.6 * knockbackResistance); // 算出实际推开的方向与强度
}
}

完整注册源码

      register(// 865
context,
PUNCH,
Enchantment.enchantment(// 868
Enchantment.definition(// 869
items.getOrThrow(ItemTags.BOW_ENCHANTABLE),// 870
2,
2,
Enchantment.dynamicCost(12, 20),// 873
Enchantment.dynamicCost(37, 20),// 874
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 879
EnchantmentEffectComponents.KNOCKBACK,
new AddValue(LevelBasedValue.perLevel(1.0F)),// 881
LootItemEntityPropertyCondition.hasProperties(// 882
LootContext.EntityTarget.DIRECT_ATTACKER, EntityPredicate.Builder.entity().of(entityTypes, EntityTypeTags.ARROWS).build()// 883
)
)
);

8.8 火矢 flame

  • 中文名:火矢
  • 命名空间 ID:flame
  • 最高等级:I
  • 描述:使射出的箭着火。
  • 适用物品:弓;ItemTags.BOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:880

详细生效链路

  1. 注册 PROJECTILE_SPAWNED 效果,执行器为 Ignite(LevelBasedValue.constant(100.0F)),即投射物生成时点燃 100 tick。
  2. 投射物真正入世界后,Projectile#applyOnProjectileSpawned(ServerLevel,ItemStack)net/minecraft/world/entity/projectile/Projectile.java:253 调用 EnchantmentHelper#onProjectileSpawned
  3. helper 会把发射武器的附魔逐个交给 Enchantment#onProjectileSpawned;火矢命中时,Ignite#apply 负责给箭实体设置燃烧时间。
  4. 之后燃烧中的箭在命中实体时会带出着火效果,因此火矢的触发时点是“生成箭”而不是“箭击中人”。
  5. 该附魔不直接增加数值伤害,伤害变化来自后续燃烧状态和实体受火逻辑。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/Projectile.java:253
public void applyOnProjectileSpawned(ServerLevel serverLevel, ItemStack pickupItemStack) { // 投射物真正生成进世界后的附魔回调
EnchantmentHelper.onProjectileSpawned(serverLevel, pickupItemStack, this, item -> {}); // 先处理投射物自身物品栈上的附魔
if (this instanceof AbstractArrow arrow) { // 如果是箭
ItemStack weapon = arrow.getWeaponItem(); // 取出发射它的武器
if (weapon != null && !weapon.isEmpty() && !pickupItemStack.getItem().equals(weapon.getItem())) { // 武器存在且不是同一个物品时
EnchantmentHelper.onProjectileSpawned(serverLevel, weapon, this, arrow::onItemBreak); // 再处理武器上的火矢等投射物生成附魔
}
}
}

完整注册源码

      register(// 887
context,
FLAME,
Enchantment.enchantment(// 890
Enchantment.definition(// 891
items.getOrThrow(ItemTags.BOW_ENCHANTABLE), 2, 1, Enchantment.constantCost(20), Enchantment.constantCost(50), 4, EquipmentSlotGroup.MAINHAND// 892 895 896
)
)
.withEffect(EnchantmentEffectComponents.PROJECTILE_SPAWNED, new Ignite(LevelBasedValue.constant(100.0F)))// 901
);

8.9 无限 infinity

  • 中文名:无限
  • 命名空间 ID:infinity
  • 最高等级:I
  • 描述:射箭时不会消耗普通箭。
  • 适用物品:弓;ItemTags.BOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:890

详细生效链路

  1. 注册 AMMO_USE 组件,并用 MatchTool.toolMatches(... Items.ARROW) 限制只对普通箭生效,同时与弓系互斥集中的其他附魔保持原版兼容规则。
  2. 武器装填弹药时,ProjectileWeaponItem#useAmmonet/minecraft/world/item/ProjectileWeaponItem.java:139EnchantmentHelper#processAmmoUse(serverLevel,weapon,projectile,1)
  3. helper 遍历武器附魔后,INFINITYSetValue(0.0F) 会把本次应消耗的箭数改成 0。
  4. useAmmo 随后走 ammoToUse <= 0 分支,创建一个 copyWithCount(1) 的临时箭堆并标记 INTANGIBLE_PROJECTILE,这样能发射但不扣背包里的真实普通箭。
  5. 由于谓词只匹配 Items.ARROW,药箭和光灵箭不会被改成 0 消耗,所以它们仍然正常扣除。

关键代码展示(逐行注释)

// net/minecraft/world/item/ProjectileWeaponItem.java:139
protected static ItemStack useAmmo(ItemStack weapon, ItemStack projectile, LivingEntity holder, boolean forceInfinite) { // 发射前决定到底消耗多少弹药
int ammoToUse = !forceInfinite && !holder.hasInfiniteMaterials() && holder.level() instanceof ServerLevel serverLevel // 非创造且不是强制无限时
? EnchantmentHelper.processAmmoUse(serverLevel, weapon, projectile, 1) // 让无限附魔改写“应消耗箭数”
: 0; // 否则视为不消耗
if (ammoToUse > projectile.getCount()) { // 想消耗的数量比现有更多
return ItemStack.EMPTY; // 发射失败
} else if (ammoToUse == 0) { // 无限附魔把消耗改成 0 时
ItemStack copy = projectile.copyWithCount(1); // 复制一发临时弹药
copy.set(DataComponents.INTANGIBLE_PROJECTILE, Unit.INSTANCE); // 标记为“不可拾取/不来自真实库存扣除”的投射物
return copy; // 返回临时弹药用于发射
} else {
ItemStack used = projectile.split(ammoToUse); // 正常从物品堆里拆出要消耗的箭
return used; // 返回真实消耗的弹药
}
}

完整注册源码

      register(// 903
context,
INFINITY,
Enchantment.enchantment(// 906
Enchantment.definition(// 907
items.getOrThrow(ItemTags.BOW_ENCHANTABLE), 1, 1, Enchantment.constantCost(20), Enchantment.constantCost(50), 8, EquipmentSlotGroup.MAINHAND// 908 911 912
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.BOW_EXCLUSIVE))// 917
.withEffect(// 918
EnchantmentEffectComponents.AMMO_USE,
new SetValue(LevelBasedValue.constant(0.0F)),// 920
MatchTool.toolMatches(ItemPredicate.Builder.item().of(items, Items.ARROW))// 921
)
);

9.1 海之眷顾 luck_of_the_sea

  • 中文名:海之眷顾
  • 命名空间 ID:luck_of_the_sea
  • 最高等级:III
  • 描述:增加钓鱼时获得宝藏的概率。
  • 适用物品:钓鱼竿;ItemTags.FISHING_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:905

详细生效链路

  1. 注册 FISHING_LUCK_BONUS,每级 AddValue(1.0F)
  2. 玩家使用鱼竿时,FishingRodItem#usenet/minecraft/world/item/FishingRodItem.java:48EnchantmentHelper#getFishingLuckBonus(serverLevel,itemStack,player) 取附魔加成。
  3. 这个值被传进 new FishingHook(player, level, luck, lureSpeed)FishingRodItem.java:49),鱼钩实体在构造时保存到字段 luck
  4. 真正抽取鱼获时,FishingHook#retrievenet/minecraft/world/entity/projectile/FishingHook.java:517this.luck + owner.getLuck() 写入 LootParams.Builder#withLuck(...)
  5. 因此海之眷顾不是直接改掉落表,而是提高 FISHING loot context 的 luck 值,让战利品表更偏向宝藏池。

关键代码展示(逐行注释)

// net/minecraft/world/item/FishingRodItem.java:46
if (level instanceof ServerLevel serverLevel) { // 服务端生成鱼钩前
int lureSpeed = (int)(EnchantmentHelper.getFishingTimeReduction(serverLevel, itemStack, player) * 20.0F); // 先算饵钓带来的等待时间缩减
int luck = EnchantmentHelper.getFishingLuckBonus(serverLevel, itemStack, player); // 再算海之眷顾带来的幸运值
FishingHook fishingHook = new FishingHook(player, level, luck, lureSpeed); // 把两者一起塞进鱼钩实体
}

// net/minecraft/world/entity/projectile/FishingHook.java:513
LootParams params = new LootParams.Builder((ServerLevel)this.level()) // 构造钓鱼战利品上下文
.withParameter(LootContextParams.ORIGIN, this.position()) // 写入鱼钩位置
.withParameter(LootContextParams.TOOL, rod) // 写入鱼竿
.withParameter(LootContextParams.THIS_ENTITY, this) // 写入当前鱼钩实体
.withLuck(this.luck + owner.getLuck()) // 关键:把海之眷顾幸运值加到 loot luck
.create(LootContextParamSets.FISHING); // 生成钓鱼专用上下文

完整注册源码

      register(// 924
context,
LUCK_OF_THE_SEA,
Enchantment.enchantment(// 927
Enchantment.definition(// 928
items.getOrThrow(ItemTags.FISHING_ENCHANTABLE),// 929
2,
3,
Enchantment.dynamicCost(15, 9),// 932
Enchantment.dynamicCost(65, 9),// 933
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(EnchantmentEffectComponents.FISHING_LUCK_BONUS, new AddValue(LevelBasedValue.perLevel(1.0F)))// 938
);

9.2 饵钓 lure

  • 中文名:饵钓
  • 命名空间 ID:lure
  • 最高等级:III
  • 描述:减少钓鱼所需的时间。
  • 适用物品:钓鱼竿;ItemTags.FISHING_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:921

详细生效链路

  1. 注册 FISHING_TIME_REDUCTION,每级 AddValue(5.0F)
  2. 鱼竿使用时,FishingRodItem#usenet/minecraft/world/item/FishingRodItem.java:47EnchantmentHelper#getFishingTimeReduction(...),再乘以 20.0F 变成 tick 数。
  3. 得到的 lureSpeed 被写进 FishingHook 构造参数,鱼钩实例保存在字段 lureSpeed
  4. 鱼钩等待鱼上钩时,FishingHook#resetTimeUntilLurednet/minecraft/world/entity/projectile/FishingHook.java:423-424this.lureSpeed 直接减少随机等待时间;计时过程中 timeUntilLured 也按加速后的值递减。
  5. 所以饵钓作用的是“缩短咬钩前等待时间”,并不改变最终抽到哪一类战利品。

关键代码展示(逐行注释)

// net/minecraft/world/item/FishingRodItem.java:46
if (level instanceof ServerLevel serverLevel) { // 抛竿时
int lureSpeed = (int)(EnchantmentHelper.getFishingTimeReduction(serverLevel, itemStack, player) * 20.0F); // 把饵钓附魔换算成 tick 级时间缩减
int luck = EnchantmentHelper.getFishingLuckBonus(serverLevel, itemStack, player); // 同时读取海之眷顾
FishingHook fishingHook = new FishingHook(player, level, luck, lureSpeed); // 把 lureSpeed 保存进鱼钩实体
}

完整注册源码

      register(// 940
context,
LURE,
Enchantment.enchantment(// 943
Enchantment.definition(// 944
items.getOrThrow(ItemTags.FISHING_ENCHANTABLE),// 945
2,
3,
Enchantment.dynamicCost(15, 9),// 948
Enchantment.dynamicCost(65, 9),// 949
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(EnchantmentEffectComponents.FISHING_TIME_REDUCTION, new AddValue(LevelBasedValue.perLevel(5.0F)))// 954
);

9.3 忠诚 loyalty

  • 中文名:忠诚
  • 命名空间 ID:loyalty
  • 最高等级:III
  • 描述:使掷出后的三叉戟返回,等级越高返回越快。
  • 适用物品:三叉戟;ItemTags.TRIDENT_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:937

详细生效链路

  1. 注册 TRIDENT_RETURN_ACCELERATION,每级 AddValue(1.0F)
  2. 投掷三叉戟创建实体时,ThrownTrident 构造函数在 net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:47this.getLoyaltyFromItem(tridentItem) 初始化同步数据。
  3. getLoyaltyFromItemThrownTrident.java:222-224EnchantmentHelper#getTridentReturnToOwnerAcceleration(serverLevel,tridentItem,this),把附魔值换算成返回加速度。
  4. 三叉戟 tick 时,ThrownTrident#tickThrownTrident.java:73-90 检查 loyalty 值;若已命中或进入 noPhysics,就按该值增加朝向持有者的速度。
  5. 等级越高,accel = 0.05 * loyalty 越大,回收越快;同时 tickDespawnThrownTrident.java:230-233 也会对高忠诚三叉戟延迟自然消失。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:222
private byte getLoyaltyFromItem(ItemStack tridentItem) { // 从三叉戟物品读取忠诚等级
return this.level() instanceof ServerLevel serverLevel // 仅服务端读取
? (byte)Mth.clamp(EnchantmentHelper.getTridentReturnToOwnerAcceleration(serverLevel, tridentItem, this), 0, 127) // 把附魔结果夹到 byte 范围
: 0; // 客户端默认 0
}

// net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:71
Entity currentOwner = this.getOwner(); // 当前持有者
int loyalty = this.entityData.get(ID_LOYALTY); // 取同步后的忠诚值
if (loyalty > 0 && (this.dealtDamage || this.isNoPhysics()) && currentOwner != null) { // 命中过后开始返回
this.setNoPhysics(true); // 回收状态不再正常碰撞
Vec3 vec = currentOwner.getEyePosition().subtract(this.position()); // 计算飞回持有者眼睛的方向
double accel = 0.05 * loyalty; // 忠诚等级越高,加速度越大
this.setDeltaMovement(this.getDeltaMovement().scale(0.95).add(vec.normalize().scale(accel))); // 每 tick 叠加回收速度
}

完整注册源码

      register(// 956
context,
LOYALTY,
Enchantment.enchantment(// 959
Enchantment.definition(// 960
items.getOrThrow(ItemTags.TRIDENT_ENCHANTABLE),// 961
5,
3,
Enchantment.dynamicCost(12, 7),// 964
Enchantment.constantCost(50),// 965
2,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(EnchantmentEffectComponents.TRIDENT_RETURN_ACCELERATION, new AddValue(LevelBasedValue.perLevel(1.0F)))// 970
);

9.4 穿刺 impaling

  • 中文名:穿刺
  • 命名空间 ID:impaling
  • 最高等级:V
  • 描述:对敏感目标造成额外伤害。
  • 适用物品:三叉戟;ItemTags.TRIDENT_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:953

详细生效链路

  1. 注册 DAMAGE 组件,条件要求受击实体匹配 EntityTypeTags.SENSITIVE_TO_IMPALING,每级额外 +2.5F
  2. 投掷命中时,ThrownTrident#onHitEntitynet/minecraft/world/entity/projectile/arrow/ThrownTrident.java:141EnchantmentHelper#modifyDamage(serverLevel,this.getWeaponItem(),entity,damageSource,dmg)
  3. 若三叉戟作为近战武器使用,则近战总伤害链也会在 LivingEntity.java:3363 通过同一个 modifyDamage helper 读取附魔。
  4. helper 遍历三叉戟上的附魔,由 Enchantment#modifyDamage 根据受害者是否属于 SENSITIVE_TO_IMPALING 决定是否叠加伤害。
  5. 最终加成后的 dmg 被送进 hurtOrSimulate,因此穿刺只改最终命中伤害,不处理返回、召雷或位移。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:135
protected void onHitEntity(EntityHitResult hitResult) { // 投掷三叉戟命中实体时
Entity entity = hitResult.getEntity(); // 当前受击目标
float dmg = (float)this.baseDamage; // 先取三叉戟基础伤害
Entity currentOwner = this.getOwner(); // 取投掷者
DamageSource damageSource = this.damageSources().trident(this, (Entity)(currentOwner == null ? this : currentOwner)); // 构造三叉戟伤害来源
if (this.level() instanceof ServerLevel serverLevel) { // 服务端下
dmg = EnchantmentHelper.modifyDamage(serverLevel, this.getWeaponItem(), entity, damageSource, dmg); // 让穿刺等附魔改写伤害
}
}

完整注册源码

      register(// 972
context,
IMPALING,
Enchantment.enchantment(// 975
Enchantment.definition(// 976
items.getOrThrow(ItemTags.TRIDENT_ENCHANTABLE),// 977
2,
5,
Enchantment.dynamicCost(1, 8),// 980
Enchantment.dynamicCost(21, 8),// 981
4,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.DAMAGE_EXCLUSIVE))// 986
.withEffect(// 987
EnchantmentEffectComponents.DAMAGE,
new AddValue(LevelBasedValue.perLevel(2.5F)),// 989
LootItemEntityPropertyCondition.hasProperties(// 990
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity().entityType(EntityTypePredicate.of(entityTypes, EntityTypeTags.SENSITIVE_TO_IMPALING)).build()// 992
)
)
);

9.5 激流 riptide

  • 中文名:激流
  • 命名空间 ID:riptide
  • 最高等级:III
  • 描述:将玩家向掷出三叉戟的方向发射,仅在水中或雨中生效。
  • 适用物品:三叉戟;ItemTags.TRIDENT_ENCHANTABLE,槽位 EquipmentSlotGroup.HAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:977

详细生效链路

  1. 注册两个 special effect:TRIDENT_SPIN_ATTACK_STRENGTHTRIDENT_SOUND,并与 RIPTIDE_EXCLUSIVE(忠诚/引雷侧)互斥。
  2. 玩家松开右键时,TridentItem#releaseUsingnet/minecraft/world/item/TridentItem.java:71EnchantmentHelper#getTridentSpinAttackStrength(itemStack, player)
  3. helper 遍历三叉戟附魔后,把激流等级换算成冲刺强度;同一方法在 TridentItem.java:76 还会通过 pickHighestLevel(... TRIDENT_SOUND) 选取对应音效。
  4. 若强度大于 0 且玩家在水中或雨中,releaseUsing 走旋转冲刺分支,把玩家沿朝向发射出去并执行旋转攻击。
  5. 相反,TridentItem#use / releaseUsing 的限制判断在 TridentItem.java:156 明确禁止“有激流强度但不在水/雨中”时释放该效果。

关键代码展示(逐行注释)

// net/minecraft/world/item/TridentItem.java:71
float riptideStrength = EnchantmentHelper.getTridentSpinAttackStrength(itemStack, player); // 读取激流附魔换算后的冲刺强度
if (!(riptideStrength > 0.0F) || player.isInWaterOrRain() && !player.isPassenger()) { // 有激流时必须在水中或雨中且不能骑乘
Holder<SoundEvent> sound = EnchantmentHelper.pickHighestLevel(itemStack, EnchantmentEffectComponents.TRIDENT_SOUND) // 读取对应等级的激流音效
.orElse(SoundEvents.TRIDENT_THROW); // 没有激流则退回普通投掷音效
}

完整注册源码

      register(// 996
context,
RIPTIDE,
Enchantment.enchantment(// 999
Enchantment.definition(// 1000
items.getOrThrow(ItemTags.TRIDENT_ENCHANTABLE),// 1001
2,
3,
Enchantment.dynamicCost(17, 7),// 1004
Enchantment.constantCost(50),// 1005
4,
EquipmentSlotGroup.HAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.RIPTIDE_EXCLUSIVE))// 1010
.withSpecialEffect(EnchantmentEffectComponents.TRIDENT_SPIN_ATTACK_STRENGTH, new AddValue(LevelBasedValue.perLevel(1.5F, 0.75F)))// 1011
.withSpecialEffect(// 1012
EnchantmentEffectComponents.TRIDENT_SOUND, List.of(SoundEvents.TRIDENT_RIPTIDE_1, SoundEvents.TRIDENT_RIPTIDE_2, SoundEvents.TRIDENT_RIPTIDE_3)// 1014
)
);

9.6 引雷 channeling

  • 中文名:引雷
  • 命名空间 ID:channeling
  • 最高等级:I
  • 描述:雷暴天气下,三叉戟命中实体或避雷针时召唤闪电。
  • 适用物品:三叉戟;ItemTags.TRIDENT_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1049

详细生效链路

  1. 注册两条效果链:POST_ATTACK(命中实体)与 HIT_BLOCK(命中方块);二者执行器都是 SummonEntityEffect(LIGHTNING_BOLT) + PlaySoundEffect
  2. 三叉戟命中实体后,ThrownTrident#onHitEntitynet/minecraft/world/entity/projectile/arrow/ThrownTrident.java:150-153EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak(...)
  3. 进入 POST_ATTACK 链后,引雷要求同时满足:世界雷暴、受击实体位置可见天空、DIRECT_ATTACKER 是三叉戟;满足后才召出闪电。
  4. 三叉戟命中方块时,ThrownTrident#hitBlockEnchantmentEffectsThrownTrident.java:168-179EnchantmentHelper#onHitBlock,随后走 HIT_BLOCK 组件分发。
  5. HIT_BLOCK 条件进一步要求命中位置是可见天空的避雷针;真正生成实体时,SummonEntityEffect 会把闪电交给服务器雷击流程。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:150
if (this.level() instanceof ServerLevel serverLevel) { // 三叉戟命中实体后
EnchantmentHelper.doPostAttackEffectsWithItemSourceOnBreak( // 分发 POST_ATTACK 附魔效果
serverLevel, entity, damageSource, this.getWeaponItem(), weapon -> this.kill(serverLevel) // 引雷命中实体的召雷逻辑就从这里继续往下走
);
}

// net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:168
protected void hitBlockEnchantmentEffects(ServerLevel level, BlockHitResult hitResult, ItemStack weapon) { // 三叉戟命中方块后的附魔回调
Vec3 compensatedHitPosition = hitResult.getBlockPos().clampLocationWithin(hitResult.getLocation()); // 计算更精确的命中坐标
EnchantmentHelper.onHitBlock( // 分发 HIT_BLOCK 类型效果
level, weapon, this.getOwner() instanceof LivingEntity livingOwner ? livingOwner : null, this, null, compensatedHitPosition, level.getBlockState(hitResult.getBlockPos()), item -> this.kill(level)
);
}

完整注册源码

      register(// 1077
context,
CHANNELING,
Enchantment.enchantment(// 1080
Enchantment.definition(// 1081
items.getOrThrow(ItemTags.TRIDENT_ENCHANTABLE),// 1082
1,
1,
Enchantment.constantCost(25),// 1085
Enchantment.constantCost(50),// 1086
8,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 1091
EnchantmentEffectComponents.POST_ATTACK,
EnchantmentTarget.ATTACKER,
EnchantmentTarget.VICTIM,
AllOf.entityEffects(// 1095
new SummonEntityEffect(HolderSet.direct(EntityType.LIGHTNING_BOLT.builtInRegistryHolder()), false),// 1096
new PlaySoundEffect(List.of(SoundEvents.TRIDENT_THUNDER), ConstantFloat.of(5.0F), ConstantFloat.of(1.0F))// 1097
),
AllOfCondition.allOf(// 1099
WeatherCheck.weather().setThundering(true),// 1100
LootItemEntityPropertyCondition.hasProperties(// 1101
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().located(LocationPredicate.Builder.location().setCanSeeSky(true))// 1102
),
LootItemEntityPropertyCondition.hasProperties(// 1104
LootContext.EntityTarget.DIRECT_ATTACKER, EntityPredicate.Builder.entity().of(entityTypes, EntityType.TRIDENT)// 1105
)
)
)
.withEffect(// 1109
EnchantmentEffectComponents.HIT_BLOCK,
AllOf.entityEffects(// 1111
new SummonEntityEffect(HolderSet.direct(EntityType.LIGHTNING_BOLT.builtInRegistryHolder()), false),// 1112
new PlaySoundEffect(List.of(SoundEvents.TRIDENT_THUNDER), ConstantFloat.of(5.0F), ConstantFloat.of(1.0F))// 1113
),
AllOfCondition.allOf(// 1115
WeatherCheck.weather().setThundering(true),// 1116
LootItemEntityPropertyCondition.hasProperties(// 1117
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().of(entityTypes, EntityType.TRIDENT)// 1118
),
LocationCheck.checkLocation(// 1120
LocationPredicate.Builder.location()// 1121
.setCanSeeSky(true)// 1122
.setBlock(net.minecraft.advancements.criterion.BlockPredicate.Builder.block().of(blocks, BlockTags.LIGHTNING_RODS))// 1123
)
)
)
);

9.7 多重射击 multishot

  • 中文名:多重射击
  • 命名空间 ID:multishot
  • 最高等级:I
  • 描述:装填时消耗一个物品以装填三个该物品。
  • 适用物品:弩;ItemTags.CROSSBOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1100

详细生效链路

  1. 注册两个数值组件:PROJECTILE_COUNT +2PROJECTILE_SPREAD +10
  2. 弩装填时,ProjectileWeaponItem#drawnet/minecraft/world/item/ProjectileWeaponItem.java:122-125 通过 EnchantmentHelper#processProjectileCount(serverLevel,weapon,shooter,1) 算出要装填的投射物数量。
  3. 多重射击把数量从 1 改到 3;随后 draw 循环里只有第一发走正常弹药消耗,额外两发会通过 forceInfinite / 临时复制堆的方式生成。
  4. 真正发射时,ProjectileWeaponItem#shootProjectileWeaponItem.java:57-58 再通过 processProjectileSpread 计算扩散角,把三发投射物分散开。
  5. 因此多重射击的链路分成“装填数量”和“发射散布”两段:前者决定会生成几发,后者决定三发之间的夹角。

关键代码展示(逐行注释)

// net/minecraft/world/item/ProjectileWeaponItem.java:118
protected static List<ItemStack> draw(ItemStack weapon, ItemStack projectile, LivingEntity shooter, boolean consume) { // 装填弩/弓时生成待发射投射物列表
if (projectile.isEmpty()) { // 没有弹药
return List.of(); // 直接返回空
} else {
int numProjectiles = shooter.level() instanceof ServerLevel serverLevel // 服务端下
? EnchantmentHelper.processProjectileCount(serverLevel, weapon, shooter, 1) // 让多重射击把“1 发”改成“3 发”
: 1;
List<ItemStack> drawn = new ArrayList<>(numProjectiles); // 按最终数量创建列表
ItemStack projectileCopy = projectile.copy(); // 复制备用弹药堆

for (int i = 0; i < numProjectiles; i++) { // 逐发装填
ItemStack drawnStack = useAmmo(weapon, i == 0 ? projectile : projectileCopy, shooter, i > 0 || !consume); // 第一发正常消耗,后两发走额外复制逻辑
if (!drawnStack.isEmpty()) {
drawn.add(drawnStack); // 收集到待发射列表
}
}

return drawn; // 返回最终装填出的投射物列表
}
}

完整注册源码

      register(// 1128
context,
MULTISHOT,
Enchantment.enchantment(// 1131
Enchantment.definition(// 1132
items.getOrThrow(ItemTags.CROSSBOW_ENCHANTABLE),// 1133
2,
1,
Enchantment.constantCost(20),// 1136
Enchantment.constantCost(50),// 1137
4,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.CROSSBOW_EXCLUSIVE))// 1142
.withEffect(EnchantmentEffectComponents.PROJECTILE_COUNT, new AddValue(LevelBasedValue.perLevel(2.0F)))// 1143
.withEffect(EnchantmentEffectComponents.PROJECTILE_SPREAD, new AddValue(LevelBasedValue.perLevel(10.0F)))// 1144
);

9.8 快速装填 quick_charge

  • 中文名:快速装填
  • 命名空间 ID:quick_charge
  • 最高等级:III
  • 描述:减少弩的填装时间。
  • 适用物品:弩;ItemTags.CROSSBOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHANDEquipmentSlotGroup.OFFHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1118

详细生效链路

  1. 注册 CROSSBOW_CHARGE_TIME special effect,每级 -0.25F,并额外注册三档 CROSSBOW_CHARGING_SOUNDS
  2. 弩计算装填时长时,CrossbowItem#getChargeDurationnet/minecraft/world/item/CrossbowItem.java:250EnchantmentHelper#modifyCrossbowChargingTime(crossbow,user,1.25F)
  3. helper 遍历附魔后,Enchantment#modifyCrossbowChargeTime 把 quick charge 的负值叠到基础装填时间上,得到更短的最终蓄力时长。
  4. 同一个物品的装填音效由 CrossbowItem#getChargingSoundsCrossbowItem.java:260 通过 pickHighestLevel(... CROSSBOW_CHARGING_SOUNDS) 选出。
  5. 因此快速装填既改变数值时间,也改变客户端/服务端播放的装填声阶段。

关键代码展示(逐行注释)

// net/minecraft/world/item/CrossbowItem.java:249
public static int getChargeDuration(ItemStack crossbow, LivingEntity user) { // 计算弩需要拉多久才算装填完成
float duration = EnchantmentHelper.modifyCrossbowChargingTime(crossbow, user, 1.25F); // 让快速装填附魔改写基础装填时间
return Mth.floor(duration * 20.0F); // 把秒制时间换算成 tick
}

// net/minecraft/world/item/CrossbowItem.java:259
CrossbowItem.ChargingSounds getChargingSounds(ItemStack itemStack) { // 取得装填音效组
return EnchantmentHelper.pickHighestLevel(itemStack, EnchantmentEffectComponents.CROSSBOW_CHARGING_SOUNDS).orElse(DEFAULT_SOUNDS); // 读 quick charge 对应的音效配置
}

完整注册源码

      register(// 1146
context,
QUICK_CHARGE,
Enchantment.enchantment(// 1149
Enchantment.definition(// 1150
items.getOrThrow(ItemTags.CROSSBOW_ENCHANTABLE),// 1151
5,
3,
Enchantment.dynamicCost(12, 20),// 1154
Enchantment.constantCost(50),// 1155
2,
EquipmentSlotGroup.MAINHAND,
EquipmentSlotGroup.OFFHAND
)
)
.withSpecialEffect(EnchantmentEffectComponents.CROSSBOW_CHARGE_TIME, new AddValue(LevelBasedValue.perLevel(-0.25F)))// 1161
.withSpecialEffect(// 1162
EnchantmentEffectComponents.CROSSBOW_CHARGING_SOUNDS,
List.of(// 1164
new CrossbowItem.ChargingSounds(
Optional.of(SoundEvents.CROSSBOW_QUICK_CHARGE_1), Optional.empty(), Optional.of(SoundEvents.CROSSBOW_LOADING_END)// 1166
),
new CrossbowItem.ChargingSounds(
Optional.of(SoundEvents.CROSSBOW_QUICK_CHARGE_2), Optional.empty(), Optional.of(SoundEvents.CROSSBOW_LOADING_END)// 1169
),
new CrossbowItem.ChargingSounds(
Optional.of(SoundEvents.CROSSBOW_QUICK_CHARGE_3), Optional.empty(), Optional.of(SoundEvents.CROSSBOW_LOADING_END)// 1172
)
)
)
);

9.9 穿透 piercing

  • 中文名:穿透
  • 命名空间 ID:piercing
  • 最高等级:IV
  • 描述:使弩箭穿过多个实体。
  • 适用物品:弩;ItemTags.CROSSBOW_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1149

详细生效链路

  1. 注册 PROJECTILE_PIERCING,每级 +1,并与多重射击同属 CROSSBOW_EXCLUSIVE 互斥集。
  2. 箭实体创建时,AbstractArrownet/minecraft/world/entity/projectile/arrow/AbstractArrow.java:123-125EnchantmentHelper#getPiercingCount(serverLevel,firedFromWeapon,pickupItemStack) 并设置 setPierceLevel(...)
  3. 这个 pierceLevel 被同步到箭实体数据里,后续命中逻辑会一直读取。
  4. 命中实体时,AbstractArrow#onHitEntity / 后续穿透逻辑在 AbstractArrow.java:471-480:544 等位置判断 getPierceLevel() > 0,决定箭是否继续存在并记录已穿透实体。
  5. 因此穿透的真正生效点不是命中时临时再算,而是在投射物生成阶段就把“可穿透层数”写进箭实体状态。

关键代码展示(逐行注释)

// net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:117
if (firedFromWeapon != null && level instanceof ServerLevel serverLevel) { // 箭知道自己由哪把武器射出时
if (firedFromWeapon.isEmpty()) { // 武器为空属于非法状态
throw new IllegalArgumentException("Invalid weapon firing an arrow"); // 直接抛异常
}

this.firedFromWeapon = firedFromWeapon.copy(); // 保存一份发射武器副本
int pierceLevel = EnchantmentHelper.getPiercingCount(serverLevel, firedFromWeapon, this.pickupItemStack); // 读取弩上的穿透等级
if (pierceLevel > 0) { // 有穿透时
this.setPierceLevel((byte)pierceLevel); // 直接写进箭实体同步数据
}
}

完整注册源码

      register(// 1177
context,
PIERCING,
Enchantment.enchantment(// 1180
Enchantment.definition(// 1181
items.getOrThrow(ItemTags.CROSSBOW_ENCHANTABLE),// 1182
10,
4,
Enchantment.dynamicCost(1, 10),// 1185
Enchantment.constantCost(50),// 1186
1,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.CROSSBOW_EXCLUSIVE))// 1191
.withEffect(EnchantmentEffectComponents.PROJECTILE_PIERCING, new AddValue(LevelBasedValue.perLevel(1.0F)))// 1192
);

10.1 致密 density

  • 中文名:致密
  • 命名空间 ID:density
  • 最高等级:V
  • 描述:增加重锤下落攻击所造成的伤害。
  • 适用物品:重锤;ItemTags.MACE_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1166

详细生效链路

  1. 注册 SMASH_DAMAGE_PER_FALLEN_BLOCK,每级 AddValue(0.5F),并与其它伤害类重锤附魔共用 DAMAGE_EXCLUSIVE 互斥集。
  2. 重锤计算下砸附加伤害时,MaceItem#getAttackDamageBonusnet/minecraft/world/item/MaceItem.java:115EnchantmentHelper#modifyFallBasedDamage(level,attacker.getWeaponItem(),victim,damageSource,0.0F)
  3. helper 遍历重锤附魔后,Enchantment#modifyFallBasedDamage 会读取 SMASH_DAMAGE_PER_FALLEN_BLOCK 组件,把“每下落一格增加多少伤害”累计进结果值。
  4. MaceItem 随后把这个每格增量乘以 fallDistance,并加到下砸总伤害中。
  5. 因此致密不直接写死一个最终伤害,而是修改“按下落距离换算伤害”的系数,坠得越高加成越大。

关键代码展示(逐行注释)

// net/minecraft/world/item/MaceItem.java:114
return attacker.level() instanceof ServerLevel level // 仅服务端做附魔修正
? (float)(damage + EnchantmentHelper.modifyFallBasedDamage(level, attacker.getWeaponItem(), victim, damageSource, 0.0F) * fallDistance) // 让致密先算“每格额外伤害”,再乘以下落距离
: (float)damage; // 客户端仅保留基础值

完整注册源码

      register(// 1194
context,
DENSITY,
Enchantment.enchantment(// 1197
Enchantment.definition(// 1198
items.getOrThrow(ItemTags.MACE_ENCHANTABLE),// 1199
5,
5,
Enchantment.dynamicCost(5, 8),// 1202
Enchantment.dynamicCost(25, 8),// 1203
2,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.DAMAGE_EXCLUSIVE))// 1208
.withEffect(EnchantmentEffectComponents.SMASH_DAMAGE_PER_FALLEN_BLOCK, new AddValue(LevelBasedValue.perLevel(0.5F)))// 1209
);

10.2 破甲 breach

  • 中文名:破甲
  • 命名空间 ID:breach
  • 最高等级:IV
  • 描述:降低攻击目标的护甲值对攻击伤害的减少效果。
  • 适用物品:重锤;ItemTags.MACE_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1183

详细生效链路

  1. 注册 ARMOR_EFFECTIVENESS,每级 AddValue(-0.15F);负值意味着削弱护甲吸收比例。
  2. 受击方进入护甲减伤结算时,CombatRules#getDamageAfterAbsorbnet/minecraft/world/damagesource/CombatRules.java:20-23 取出 source.getWeaponItem() 并调用 EnchantmentHelper#modifyArmorEffectiveness
  3. helper 遍历攻击武器上的附魔,由 Enchantment#modifyArmorEffectiveness 读取 ARMOR_EFFECTIVENESS 组件,对当前 armorFraction 做负向修正。
  4. CombatRules 再把修正后的护甲比例夹到 0.0F~1.0F 并换算成最终伤害倍率,所以破甲作用在“护甲吸收比例”这一步,而不是直接给伤害加值。
  5. 结果就是目标护甲仍然参与结算,但其减伤效率被下调;等级越高,护甲对这次攻击的保护越弱。

关键代码展示(逐行注释)

// net/minecraft/world/damagesource/CombatRules.java:16
public static float getDamageAfterAbsorb(LivingEntity victim, float damage, DamageSource source, float totalArmor, float armorToughness) { // 护甲减伤核心公式
float toughness = 2.0F + armorToughness / 4.0F; // 先计算护甲韧性对减伤曲线的影响
float realArmor = Mth.clamp(totalArmor - damage / toughness, totalArmor * 0.2F, 20.0F); // 算出本次命中的有效护甲
float armorFraction = realArmor / 25.0F; // 换成“护甲吸收比例”
ItemStack weaponItem = source.getWeaponItem(); // 取本次伤害对应的武器
float modifiedArmorFraction;
if (weaponItem != null && victim.level() instanceof ServerLevel level) { // 武器存在且在服务端时
modifiedArmorFraction = Mth.clamp(EnchantmentHelper.modifyArmorEffectiveness(level, weaponItem, victim, source, armorFraction), 0.0F, 1.0F); // 让破甲附魔修改护甲吸收比例
} else {
modifiedArmorFraction = armorFraction; // 否则按原比例结算
}

float damageMultiplier = 1.0F - modifiedArmorFraction; // 把护甲比例转成最终伤害倍率
return damage * damageMultiplier; // 返回护甲结算后的伤害
}

完整注册源码

      register(// 1211
context,
BREACH,
Enchantment.enchantment(// 1214
Enchantment.definition(// 1215
items.getOrThrow(ItemTags.MACE_ENCHANTABLE),// 1216
2,
4,
Enchantment.dynamicCost(15, 9),// 1219
Enchantment.dynamicCost(65, 9),// 1220
4,
EquipmentSlotGroup.MAINHAND
)
)
.exclusiveWith(enchantments.getOrThrow(EnchantmentTags.DAMAGE_EXCLUSIVE))// 1225
.withEffect(EnchantmentEffectComponents.ARMOR_EFFECTIVENESS, new AddValue(LevelBasedValue.perLevel(-0.15F)))// 1226
);

10.3 风爆 wind_burst

  • 中文名:风爆
  • 命名空间 ID:wind_burst
  • 最高等级:III
  • 描述:使重锤下落时击中目标后产生风爆,将攻击者向上弹起。
  • 适用物品:重锤;ItemTags.MACE_ENCHANTABLE,槽位 EquipmentSlotGroup.MAINHAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1200

详细生效链路

  1. 注册 POST_ATTACKenchanted = ATTACKERaffected = ATTACKER,执行器为 ExplodeEffect;条件要求 DIRECT_ATTACKER 未飞行且下落距离至少 1.5
  2. 近战命中成功后,玩家与怪物都会在攻击链末尾调用 EnchantmentHelper#doPostAttackEffects(如 LivingEntity.java:3381Mob.java:1624)。
  3. helper 分发到 Enchantment#doPostAttack 后,风爆的目标仍然是攻击者本人,所以效果不是打在受害者身上,而是打在挥锤者当前位置。
  4. ExplodeEffect#applynet/minecraft/world/item/enchantment/effects/ExplodeEffect.java:61-82serverLevel.explode(...),使用风弹式粒子、音效和击退倍率配置。
  5. 因此风爆的本质是“下砸命中后立刻在攻击者脚下触发一次受控爆炸”,把攻击者向上弹起,形成连跳或二段下砸机会。

关键代码展示(逐行注释)

// net/minecraft/world/item/enchantment/effects/ExplodeEffect.java:61
public void apply(ServerLevel serverLevel, int enchantmentLevel, EnchantedItemInUse item, Entity entity, Vec3 position) { // 风爆最终执行器
Vec3 pos = position.add(this.offset); // 先得到爆炸中心点
serverLevel.explode( // 直接调用服务器爆炸逻辑
this.attributeToUser ? entity : null, // 是否把爆炸归因到攻击者
this.getDamageSource(entity, pos), // 构造爆炸伤害来源
new SimpleExplosionDamageCalculator( // 构造爆炸伤害/击退计算器
this.blockInteraction != Level.ExplosionInteraction.NONE, // 是否影响方块
this.damageType.isPresent(), // 是否有明确伤害类型
this.knockbackMultiplier.map(value -> value.calculate(enchantmentLevel)), // 按附魔等级算击退倍率
this.immuneBlocks // 免疫方块集合
),
pos.x(), pos.y(), pos.z(), // 爆炸坐标
Math.max(this.radius.calculate(enchantmentLevel), 0.0F), // 爆炸半径
this.createFire, // 是否点火
this.blockInteraction, // 方块交互方式
this.smallParticle, this.largeParticle, this.blockParticles, this.sound // 粒子与音效
);
}

完整注册源码

      register(// 1228
context,
WIND_BURST,
Enchantment.enchantment(// 1231
Enchantment.definition(// 1232
items.getOrThrow(ItemTags.MACE_ENCHANTABLE),// 1233
2,
3,
Enchantment.dynamicCost(15, 9),// 1236
Enchantment.dynamicCost(65, 9),// 1237
4,
EquipmentSlotGroup.MAINHAND
)
)
.withEffect(// 1242
EnchantmentEffectComponents.POST_ATTACK,
EnchantmentTarget.ATTACKER,
EnchantmentTarget.ATTACKER,
new ExplodeEffect(
false,
Optional.empty(),// 1248
Optional.of(LevelBasedValue.lookup(List.of(1.2F, 1.75F, 2.2F), LevelBasedValue.perLevel(1.5F, 0.35F))),// 1249
blocks.get(BlockTags.BLOCKS_WIND_CHARGE_EXPLOSIONS).map(Function.identity()),// 1250
Vec3.ZERO,
LevelBasedValue.constant(3.5F),// 1252
false,
Level.ExplosionInteraction.TRIGGER,
ParticleTypes.GUST_EMITTER_SMALL,
ParticleTypes.GUST_EMITTER_LARGE,
WeightedList.of(),// 1257
SoundEvents.WIND_CHARGE_BURST
),
LootItemEntityPropertyCondition.hasProperties(// 1260
LootContext.EntityTarget.DIRECT_ATTACKER,
EntityPredicate.Builder.entity()// 1262
.flags(EntityFlagsPredicate.Builder.flags().setIsFlying(false))// 1263
.moving(MovementPredicate.fallDistance(MinMaxBounds.Doubles.atLeast(1.5)))// 1264
)
)
);

10.4 突进 lunge

  • 中文名:突进
  • 命名空间 ID:lunge
  • 最高等级:III
  • 描述:进行戳刺攻击时在攻击方向上移动一段距离,并附带耐久与体力代价。
  • 适用物品:可突进武器;ItemTags.LUNGE_ENCHANTABLE,槽位 EquipmentSlotGroup.HAND
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:997

详细生效链路

  1. 注册 POST_PIERCING_ATTACK,执行器是 AllOf.entityEffects(...),组合了 ChangeItemDamageApplyExhaustionApplyEntityImpulsePlaySoundEffect
  2. 戳刺武器组件执行攻击时,PiercingWeapon#attacknet/minecraft/world/item/component/PiercingWeapon.java:84attacker.postPiercingAttack()
  3. LivingEntity#postPiercingAttacknet/minecraft/world/entity/LivingEntity.java:2068 把流程转给 EnchantmentHelper#doPostPiercingAttackEffects(serverLevel,this)
  4. helper 遍历当前武器附魔,Enchantment#doPostPiercingAttacknet/minecraft/world/item/enchantment/Enchantment.java:308)检查条件后执行各个实体效果:扣 1 点耐久、按等级增加饥饿消耗、沿朝向施加冲量,并播放突进音效。
  5. 注册条件还额外限制了不可骑乘、不可鞘翅飞行、不可在水中,以及玩家至少要有足够饱食度,所以突进不是“任何戳刺都能白嫖位移”,而是带状态门槛的动作强化。

关键代码展示(逐行注释)

// net/minecraft/world/item/component/PiercingWeapon.java:72
public void attack(LivingEntity attacker, EquipmentSlot hand) { // 戳刺武器的攻击主流程
float damage = (float)attacker.getAttributeValue(Attributes.ATTACK_DAMAGE); // 读取攻击者基础攻击力
ItemStack weaponItem = attacker.getItemBySlot(hand); // 取出手上的武器
AttackRange attackRange = attacker.getAttackRangeWith(weaponItem); // 计算戳刺攻击距离

for (EntityHitResult hitResult : ProjectileUtil.getHitEntitiesAlong(attacker, attackRange, e1 -> canHitEntity(attacker, e1), ClipContext.Block.COLLIDER).map(a -> List.of(), Function.identity())) { // 沿攻击方向搜命中实体
attacker.stabAttack(hand, hitResult.getEntity(), damage, true, this.dealsKnockback, this.dismounts); // 对每个命中目标执行戳刺伤害
}

attacker.onAttack(); // 记录一次攻击动作
attacker.postPiercingAttack(); // 然后统一触发 lunge 的 POST_PIERCING_ATTACK 附魔链
}

完整注册源码

      register(// 1017
context,
LUNGE,
Enchantment.enchantment(// 1020
Enchantment.definition(// 1021
items.getOrThrow(ItemTags.LUNGE_ENCHANTABLE), 5, 3, Enchantment.dynamicCost(5, 8), Enchantment.dynamicCost(25, 8), 2, EquipmentSlotGroup.HAND// 1022 1025 1026
)
)
.withEffect(// 1031
EnchantmentEffectComponents.POST_PIERCING_ATTACK,
AllOf.entityEffects(// 1033
new ChangeItemDamage(new LevelBasedValue.Constant(1.0F)),
new ApplyExhaustion(LevelBasedValue.perLevel(4.0F)),// 1035
new ApplyEntityImpulse(new Vec3(0.0, 0.0, 1.0), new Vec3(1.0, 0.0, 1.0), LevelBasedValue.perLevel(0.458F)),// 1036
new PlaySoundEffect(List.of(SoundEvents.LUNGE_1, SoundEvents.LUNGE_2, SoundEvents.LUNGE_3), ConstantFloat.of(1.0F), ConstantFloat.of(1.0F))// 1038
),
AllOfCondition.allOf(// 1041
InvertedLootItemCondition.invert(// 1042
LootItemEntityPropertyCondition.hasProperties(// 1043
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().vehicle(EntityPredicate.Builder.entity())// 1044
)
),
LootItemEntityPropertyCondition.hasProperties(// 1047
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().flags(EntityFlagsPredicate.Builder.flags().setIsFallFlying(false))// 1048
),
LootItemEntityPropertyCondition.hasProperties(// 1050
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().flags(EntityFlagsPredicate.Builder.flags().setIsInWater(false))// 1051
),
AnyOfCondition.anyOf(// 1053
InvertedLootItemCondition.invert(// 1054
LootItemEntityPropertyCondition.hasProperties(// 1055
LootContext.EntityTarget.THIS, EntityPredicate.Builder.entity().subPredicate(PlayerPredicate.Builder.player().build())// 1056
)
),
LootItemEntityPropertyCondition.hasProperties(// 1059
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity()// 1061
.subPredicate(PlayerPredicate.Builder.player().setGameType(GameTypePredicate.of(GameType.CREATIVE)).build())// 1062
),
LootItemEntityPropertyCondition.hasProperties(// 1064
LootContext.EntityTarget.THIS,
EntityPredicate.Builder.entity()// 1066
.subPredicate(// 1067
PlayerPredicate.Builder.player()// 1068
.setFood(FoodPredicate.Builder.food().withLevel(MinMaxBounds.Ints.atLeast(Mth.floor(6.0F) + 1)).build())// 1069
.build()// 1070
)
)
)
)
)
);

10.5 经验修补 mending

  • 中文名:经验修补
  • 命名空间 ID:mending
  • 最高等级:I
  • 描述:消耗获得的经验以修补工具或盔甲的耐久度。
  • 适用物品:可耐久附魔物品;ItemTags.DURABILITY_ENCHANTABLE,槽位 EquipmentSlotGroup.ANY
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1240

详细生效链路

  1. 注册 REPAIR_WITH_XP,数值效果为 MultiplyValue(2.0F),表示每点经验可换算成更多耐久修复量。
  2. 经验球被玩家拾取时,ExperienceOrb#repairPlayerItemsnet/minecraft/world/entity/ExperienceOrb.java:380 先通过 EnchantmentHelper#getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged) 随机挑选一个带修补且已受损的装备。
  3. 选中后,ExperienceOrb.java:383EnchantmentHelper#modifyDurabilityToRepairFromXp(player.level(), itemStack, amount),helper 遍历该物品附魔,把 REPAIR_WITH_XP 效果应用到“本次经验最多能修多少耐久”上。
  4. 随后 ExperienceOrb.java:384-393 计算本次实际修复值、触发 PlayerItemMendEvent,并直接减少 itemStack 的 damage value;剩余经验再递归尝试继续修其他可修物品。
  5. 因此经验修补的关键不是在物品自己 tick,而是在经验球吸收路径里“先修装备,再把剩余经验给玩家经验条”。

关键代码展示(逐行注释)

// net/minecraft/world/entity/ExperienceOrb.java:379
private int repairPlayerItems(ServerPlayer player, int amount) { // 经验球优先修理装备的入口
Optional<EnchantedItemInUse> selected = EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged); // 随机挑一个带修补且已损坏的装备
if (selected.isPresent()) {
ItemStack itemStack = selected.get().itemStack(); // 取出被选中的装备
int toRepairFromXpAmount = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.level(), itemStack, amount); // 让修补附魔把经验值换算成可修复耐久
int repair = Math.min(toRepairFromXpAmount, itemStack.getDamageValue()); // 最多只能修到不损坏
int consumedExperience = repair > 0 ? repair * amount / toRepairFromXpAmount : 0; // 反推这次真正消耗了多少经验
PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemStack, selected.get().inSlot(), repair, consumedExperience); // 抛出修补事件
repair = event.getRepairAmount(); // 读取事件后允许的修补值
if (event.isCancelled()) {
return amount; // 取消则经验原样返回
} else {
itemStack.setDamageValue(itemStack.getDamageValue() - repair); // 真正减少物品 damage value
}
}
}

完整注册源码

      register(// 1268
context,
MENDING,
Enchantment.enchantment(// 1271
Enchantment.definition(// 1272
items.getOrThrow(ItemTags.DURABILITY_ENCHANTABLE),// 1273
2,
1,
Enchantment.dynamicCost(25, 25),// 1276
Enchantment.dynamicCost(75, 25),// 1277
4,
EquipmentSlotGroup.ANY
)
)
.withEffect(EnchantmentEffectComponents.REPAIR_WITH_XP, new MultiplyValue(LevelBasedValue.constant(2.0F)))// 1282
);

10.6 消失诅咒 vanishing_curse

  • 中文名:消失诅咒
  • 命名空间 ID:vanishing_curse
  • 最高等级:I
  • 描述:在生物死亡时,受影响物品会消失而不掉落。
  • 适用物品:可消失诅咒物品;ItemTags.VANISHING_ENCHANTABLE,槽位 EquipmentSlotGroup.ANY
  • 注册位置:net/minecraft/world/item/enchantment/Enchantments.java:1256

详细生效链路

  1. 注册 PREVENT_EQUIPMENT_DROP,没有额外数值,语义就是“这件装备在死亡掉落阶段不要生成掉落物”。
  2. 玩家死亡清空背包前,Player#dropEquipmentnet/minecraft/world/entity/player/Player.java:606-607 会检查 EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP);命中后直接把该格物品移除而不掉出。
  3. 服务端玩家保留/掉落清单处理中,ServerPlayer.java:1153ServerPlayer.java:1204 也会再次跳过带 PREVENT_EQUIPMENT_DROP 的物品。
  4. 普通生物和可装备实体的死亡掉落同样会做过滤,例如 Mob#dropCustomDeathLootnet/minecraft/world/entity/Mob.java:1064AbstractHorse.java:529Allay.java:424
  5. 所以消失诅咒不是“把掉落物生成后再删除”,而是在各类死亡掉落入口就直接拦截,令该物品既不进入掉落表也不落地。

关键代码展示(逐行注释)

// net/minecraft/world/entity/player/Player.java:604
for (int i = 0; i < this.inventory.getContainerSize(); i++) { // 玩家死亡清理背包时逐格检查
ItemStack itemStack = this.inventory.getItem(i); // 取出当前格物品
if (!itemStack.isEmpty() && EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) { // 如果这格物品带有消失诅咒
this.inventory.removeItemNoUpdate(i); // 直接从背包里移除,不生成掉落物
}
}

// net/minecraft/server/level/ServerPlayer.java:1151
private static boolean shouldKeepDeathEventItem(PlayerDeathEvent event, net.minecraft.world.item.ItemStack item) { // 死亡事件保留物品时的辅助判断
List<ItemStack> itemsToKeep = event.getItemsToKeep(); // 取出事件层声明的保留物品
if (!EnchantmentHelper.has(item, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP) && !itemsToKeep.isEmpty() && !item.isEmpty()) { // 带消失诅咒的物品不会进入保留/掉落清单比较
// 下面才继续做普通物品的保留判断
}
}

完整注册源码

      register(// 1284
context,
VANISHING_CURSE,
Enchantment.enchantment(// 1287
Enchantment.definition(// 1288
items.getOrThrow(ItemTags.VANISHING_ENCHANTABLE), 1, 1, Enchantment.constantCost(25), Enchantment.constantCost(50), 8, EquipmentSlotGroup.ANY// 1289 1292 1293
)
)
.withEffect(EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)// 1298
);