本文档基于 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_affinity | I | 增加水下挖掘速度 |
| 节肢杀手 | bane_of_arthropods | V | 对节肢生物造成额外伤害并附加缓慢效果 |
| 爆炸保护 | blast_protection | IV | 减少受到的爆炸伤害,减少受到的爆炸击退 |
| 破甲 | breach | IV | 降低攻击目标的护甲值对攻击伤害的减少效果 |
| 引雷 | channeling | I | 使三叉戟击中实体时召唤闪电,仅在雷暴且被命中实体暴露于天空下时生效 |
| 绑定诅咒 | binding_curse | I | 受影响物品在装备时不能被卸下,创造模式不受影响 |
| 消失诅咒 | vanishing_curse | I | 在生物死亡时,受影响物品会消失而不掉落 |
| 致密 | density | V | 增加重锤下落攻击所造成的伤害 |
| 深海探索者 | depth_strider | III | 增加水下行走速度 |
| 效率 | efficiency | V | 加快挖掘速度 |
| 摔落缓冲 | feather_falling | IV | 减少受到的摔落伤害 |
| 火焰附加 | fire_aspect | II | 使被近战攻击目标着火 |
| 火焰保护 | fire_protection | IV | 减少受到的火焰伤害和着火时间 |
| 火矢 | flame | I | 使射出的箭着火 |
| 时运 | fortune | III | 增加方块掉落物的数量或概率 |
| 冰霜行者 | frost_walker | II | 使在水面行走时产生霜冰,且不会受到踩踏燃烧伤害 |
| 穿刺 | impaling | V | 对敏感目标造成额外伤害 |
| 无限 | infinity | I | 射箭时不会消耗普通箭 |
| 击退 | knockback | II | 增加近战攻击造成的击退距离 |
| 抢夺 | looting | III | 增加生物掉落物的数量或概率 |
| 忠诚 | loyalty | III | 使掷出后的三叉戟返回,等级越高返回越快 |
| 海之眷顾 | luck_of_the_sea | III | 增加钓鱼时获得宝藏的概率 |
| 突进 | lunge | III | 进行戳刺攻击时在攻击方向上移动一段距离 |
| 饵钓 | lure | III | 减少钓鱼所需的时间 |
| 经验修补 | mending | I | 消耗获得的经验以修补工具或盔甲耐久 |
| 多重射击 | multishot | I | 装填时消耗一个物品以装填三个该物品 |
| 穿透 | piercing | IV | 使箭穿过多个实体 |
| 力量 | power | V | 增加箭伤害 |
| 弹射物保护 | projectile_protection | IV | 减少受到的弹射物伤害 |
| 保护 | protection | IV | 减少受到的大多数种类的伤害 |
| 冲击 | punch | II | 增加箭的击退距离 |
| 快速装填 | quick_charge | III | 减少弩的填装时间 |
| 水下呼吸 | respiration | III | 延长水下呼吸时间 |
| 激流 | riptide | III | 将玩家向掷出三叉戟的方向发射,仅在水中或雨中生效 |
| 锋利 | sharpness | V | 增加近战攻击伤害 |
| 精准采集 | silk_touch | I | 使部分被开采的方块掉落其方块物品而非普通掉落 |
| 亡灵杀手 | smite | V | 对亡灵生物造成额外伤害 |
| 灵魂疾行 | soul_speed | III | 增加玩家在灵魂沙和灵魂土上的移动速度 |
| 横扫之刃 | sweeping_edge | III | 增加横扫攻击伤害 |
| 迅捷潜行 | swift_sneak | III | 提高玩家潜行、爬行时的移动速度 |
| 荆棘 | thorns | III | 给予攻击者伤害 |
| 耐久 | unbreaking | III | 减少触发耐久消耗的概率 |
| 风爆 | wind_burst | III | 使重锤下落时击中目标后产生风爆,将攻击者向上弹起 |
1. 总体模型
1.1 附魔不是硬编码子类,而是“注册数据 + 效果组件”
核心定义:
net/minecraft/world/item/enchantment/Enchantments.java:87:定义所有原版附魔ResourceKey<Enchantment>。net/minecraft/world/item/enchantment/Enchantments.java:131:bootstrap注册每个附魔的适用物品、等级、成本、互斥集合和效果组件。net/minecraft/world/item/enchantment/Enchantment.java:61:Enchantment是 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 数值处理器
AddValue:net/minecraft/world/item/enchantment/effects/AddValue.java:14,返回input + value(level)。MultiplyValue:net/minecraft/world/item/enchantment/effects/MultiplyValue.java:14,返回input * factor(level)。SetValue:net/minecraft/world/item/enchantment/effects/SetValue.java:14,返回固定value(level)。RemoveBinomial:net/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 实体效果处理器
DamageEntity:net/minecraft/world/item/enchantment/effects/DamageEntity.java:26,造成随机范围伤害。Ignite:net/minecraft/world/item/enchantment/effects/Ignite.java:20,点燃实体。ApplyMobEffect:net/minecraft/world/item/enchantment/effects/ApplyMobEffect.java:37,施加药水效果。ChangeItemDamage:net/minecraft/world/item/enchantment/effects/ChangeItemDamage.java:19,改变物品耐久。ApplyEntityImpulse:net/minecraft/world/item/enchantment/effects/ApplyEntityImpulse.java:24,给实体冲量。ExplodeEffect:net/minecraft/world/item/enchantment/effects/ExplodeEffect.java:61,创建爆炸。PlaySoundEffect:net/minecraft/world/item/enchantment/effects/PlaySoundEffect.java:29,播放声音。SpawnParticlesEffect:net/minecraft/world/item/enchantment/effects/SpawnParticlesEffect.java:57,发送粒子。
4.3 位置效果处理器
EnchantmentAttributeEffect:net/minecraft/world/item/enchantment/effects/EnchantmentAttributeEffect.java:40,激活时添加临时属性,失效时移除。ReplaceDisk:net/minecraft/world/item/enchantment/effects/ReplaceDisk.java:42,以实体位置为中心替换圆盘区域方块,典型用于冰霜行者。
5. 全部附魔生效链路
5.1 护甲保护类
protection
- 定义:
net/minecraft/world/item/enchantment/Enchantments.java:137 - 效果:
DAMAGE_PROTECTION,AddValue(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#getDamageProtection、ItemStack#forEachModifier - 生效位置:减伤在
LivingEntity.java:2280;燃烧时间在LivingEntity.java:4644
feather_falling
- 定义:
net/minecraft/world/item/enchantment/Enchantments.java:196 - 效果:对
DamageTypeTags.IS_FALL的DAMAGE_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_PROJECTILE的DAMAGE_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_CHANGED用ReplaceDisk把脚下水变霜冰。 - 触发入口:
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_SPEED与MOVEMENT_EFFICIENCY - 效果 2:灵魂方块上移动时概率损耗耐久。
- 效果 3:
TICK粒子和声音。 - 触发入口:
LivingEntity.java:470和LivingEntity.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 - 效果:
DAMAGE,AddValue(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:26和ChangeItemDamage.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_ATTACKER时DAMAGE +1 + 0.5*(level-1) - 生效位置:
net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:466
punch
- 定义:
net/minecraft/world/item/enchantment/Enchantments.java:858 - 效果:箭实体作为
DIRECT_ATTACKER时KNOCKBACK +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_STRENGTH和TRIDENT_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 +2、PROJECTILE_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_XP,MultiplyValue(2.0F) - 生效位置:
net/minecraft/world/entity/ExperienceOrb.java:379 - 核心链路:
- 经验球被玩家拾取。
getRandomItemWith(REPAIR_WITH_XP, player, ItemStack::isDamaged)随机选装备。modifyDurabilityToRepairFromXp计算修复量。- 减少物品 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. 附魔效果组件到附魔名称的索引
| 附魔 | 主要组件 | 主要计算/生效方法 |
|---|---|---|
protection | DAMAGE_PROTECTION | getDamageProtection |
fire_protection | DAMAGE_PROTECTION, ATTRIBUTES | getDamageProtection, ItemStack#forEachModifier |
feather_falling | DAMAGE_PROTECTION | getDamageProtection |
blast_protection | DAMAGE_PROTECTION, ATTRIBUTES | getDamageProtection, explosion knockback attribute |
projectile_protection | DAMAGE_PROTECTION | getDamageProtection |
respiration | ATTRIBUTES | OXYGEN_BONUS |
aqua_affinity | ATTRIBUTES | SUBMERGED_MINING_SPEED |
thorns | POST_ATTACK | doPostAttackEffects |
depth_strider | ATTRIBUTES | WATER_MOVEMENT_EFFICIENCY |
frost_walker | DAMAGE_IMMUNITY, LOCATION_CHANGED | isImmuneToDamage, runLocationChangedEffects |
binding_curse | PREVENT_ARMOR_CHANGE | Equippable#swapWithEquipmentSlot |
soul_speed | LOCATION_CHANGED, TICK | runLocationChangedEffects, tickEffects |
swift_sneak | ATTRIBUTES | SNEAKING_SPEED |
sharpness | DAMAGE | modifyDamage |
smite | DAMAGE | modifyDamage |
bane_of_arthropods | DAMAGE, POST_ATTACK | modifyDamage, doPostAttackEffects |
knockback | KNOCKBACK | modifyKnockback |
fire_aspect | POST_ATTACK, tag SMELTS_LOOT | doPostAttackEffects, loot predicate |
looting | EQUIPMENT_DROPS, loot functions | processEquipmentDropChance, loot count functions |
sweeping_edge | ATTRIBUTES | SWEEPING_DAMAGE_RATIO |
efficiency | ATTRIBUTES | MINING_EFFICIENCY |
silk_touch | BLOCK_EXPERIENCE, tags | block loot / special block logic |
unbreaking | ITEM_DAMAGE | processDurabilityChange |
fortune | loot functions | ApplyBonusCount |
power | DAMAGE | AbstractArrow#onHitEntity |
punch | KNOCKBACK | AbstractArrow#onHitEntity |
flame | PROJECTILE_SPAWNED | Projectile#applyOnProjectileSpawned |
infinity | AMMO_USE | ProjectileWeaponItem#useAmmo |
luck_of_the_sea | FISHING_LUCK_BONUS | FishingRodItem#use |
lure | FISHING_TIME_REDUCTION | FishingRodItem#use |
loyalty | TRIDENT_RETURN_ACCELERATION | ThrownTrident#getLoyaltyFromItem |
impaling | DAMAGE | modifyDamage |
riptide | TRIDENT_SPIN_ATTACK_STRENGTH, TRIDENT_SOUND | TridentItem#releaseUsing |
channeling | POST_ATTACK, HIT_BLOCK | trident hit entity/block |
multishot | PROJECTILE_COUNT, PROJECTILE_SPREAD | ProjectileWeaponItem#draw, shoot |
quick_charge | CROSSBOW_CHARGE_TIME, CROSSBOW_CHARGING_SOUNDS | CrossbowItem#getChargeDuration |
piercing | PROJECTILE_PIERCING | AbstractArrow constructor |
density | SMASH_DAMAGE_PER_FALLEN_BLOCK | MaceItem#getAttackDamageBonus |
breach | ARMOR_EFFECTIVENESS | CombatRules#getDamageAfterAbsorb |
wind_burst | POST_ATTACK + ExplodeEffect | doPostAttackEffects |
lunge | POST_PIERCING_ATTACK | LivingEntity#postPiercingAttack |
mending | REPAIR_WITH_XP | ExperienceOrb#repairPlayerItems |
vanishing_curse | PREVENT_EQUIPMENT_DROP | death/equipment drop filtering |
6.1 保护 protection
- 中文名:保护
- 命名空间 ID:
protection - 最高等级:IV
- 描述:减少受到的大多数种类的伤害。
- 适用物品:盔甲;代码为 ItemTags.ARMOR_ENCHANTABLE,槽位 EquipmentSlotGroup.ARMOR。
- 注册位置:
net/minecraft/world/item/enchantment/Enchantments.java:137
详细生效链路
- 注册为
DAMAGE_PROTECTION,每级AddValue(1.0F),过滤条件排除DamageTypeTags.BYPASSES_INVULNERABILITY。 - 实体受伤进入
LivingEntity#getDamageAfterMagicAbsorb(DamageSource,float):float;若伤害不绕过附魔,调用EnchantmentHelper#getDamageProtection(ServerLevel,LivingEntity,DamageSource):float。 getDamageProtection遍历受害者所有装备槽,匹配ARMOR槽位后调用Enchantment#modifyDamageProtection。Enchantment#modifyDamageProtection构造ENCHANTED_DAMAGE上下文,条件通过后把保护值累计到MutableFloat。- 最终
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
详细生效链路
- 注册为火焰条件下的
DAMAGE_PROTECTION,每级AddValue(2.0F),仅匹配DamageTypeTags.IS_FIRE。 - 减伤链路与保护相同:
LivingEntity#getDamageAfterMagicAbsorb->EnchantmentHelper#getDamageProtection->Enchantment#modifyDamageProtection。 - 额外注册
ATTRIBUTES:Attributes.BURNING_TIME,每级-0.15F,操作为ADD_MULTIPLIED_BASE。 - 装备属性由
ItemStack#forEachModifier合并EnchantmentHelper#forEachModifier注入实体属性。 - 实体被点燃时
LivingEntity#igniteForTicks(int):void按BURNING_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
详细生效链路
- 注册为
DAMAGE_PROTECTION,每级AddValue(3.0F),仅匹配DamageTypeTags.IS_FALL。 - 摔落伤害在实体通用受伤流程里进入
LivingEntity#getDamageAfterMagicAbsorb。 EnchantmentHelper#getDamageProtection遍历受害者装备并调用Enchantment#modifyDamageProtection。- loot context 中
DAMAGE_SOURCE被判定为 fall 后,摔落缓冲的保护值累计。 - 累计保护值参与最终附魔减伤,因此实际摔落伤害降低。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册为爆炸条件下的
DAMAGE_PROTECTION,每级AddValue(2.0F),匹配DamageTypeTags.IS_EXPLOSION。 - 爆炸伤害进入
LivingEntity#getDamageAfterMagicAbsorb时,通过EnchantmentHelper#getDamageProtection叠加保护值。 - 额外注册
ATTRIBUTES:Attributes.EXPLOSION_KNOCKBACK_RESISTANCE,每级+0.15F。 - 属性通过
ItemStack#forEachModifier->EnchantmentHelper#forEachModifier注入实体属性表。 - 爆炸击退逻辑读取该属性,因此不仅伤害降低,击退也会被削弱。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册为
DAMAGE_PROTECTION,每级AddValue(2.0F),仅匹配DamageTypeTags.IS_PROJECTILE。 - 箭、三叉戟等造成的伤害在实体防御阶段进入
LivingEntity#getDamageAfterMagicAbsorb。 - helper 遍历受害者装备,调用
Enchantment#modifyDamageProtection。 - 只有当
DAMAGE_SOURCE被判定为 projectile 时才累计保护值。 - 最终返回的保护值用于减小弹射物造成的伤害。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
ATTRIBUTES:Attributes.OXYGEN_BONUS,每级+1.0F。 - 装备后,
ItemStack#forEachModifier会把附魔属性和物品原生属性一起交给实体属性系统。 EnchantmentHelper#forEachModifier读取ATTRIBUTES组件并为当前槽位生成AttributeModifier。- 实体的空气/溺水逻辑读取
Attributes.OXYGEN_BONUS,关键读取位置在LivingEntity.java:638。 - 因此该附魔通过属性长期提高氧气缓冲,而不是通过 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
详细生效链路
- 注册
ATTRIBUTES:Attributes.SUBMERGED_MINING_SPEED,数值为+4.0F,操作为ADD_MULTIPLIED_TOTAL。 - 装备属性注入链路为
ItemStack#forEachModifier->EnchantmentHelper#forEachModifier。 - 玩家计算挖掘速度时会读取
SUBMERGED_MINING_SPEED,关键位置在Player.java:651。 - 无该附魔时水下挖掘有明显惩罚;该属性提高水下挖掘倍率。
- 所以它是纯属性型附魔,不走攻击、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
详细生效链路
- 注册
POST_ATTACK,声明 enchanted=VICTIM,affected=ATTACKER。 - 实体被攻击且伤害成功后,
EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak先遍历受害者装备。 - 如果装备有荆棘,
Enchantment#doPostAttack检查随机概率0.15 * level。 - 条件通过后执行
DamageEntity(1..5, DamageTypes.THORNS)对攻击者反伤。 - 同一个效果组里还执行
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
详细生效链路
- 注册
ATTRIBUTES:Attributes.WATER_MOVEMENT_EFFICIENCY,每级+0.33333334F。 - 装备时通过
ItemStack#forEachModifier与EnchantmentHelper#forEachModifier合并到实体属性。 - 水中移动逻辑读取
Attributes.WATER_MOVEMENT_EFFICIENCY,关键位置LivingEntity.java:3010。 - 该附魔与冰霜行者在
BOOTS_EXCLUSIVE标签中互斥,附魔选择与铁砧合并都受Enchantment.areCompatible约束。 - 最终效果是减轻水中水平移动惩罚,提高行走速度。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
DAMAGE_IMMUNITY,匹配DamageTypeTags.BURN_FROM_STEPPING,用于免疫岩浆块/营火等踩踏伤害。 - 实体判定是否对伤害无敌时,
LivingEntity#isInvulnerableTo调用EnchantmentHelper#isImmuneToDamage。 - 同时注册
LOCATION_CHANGED;当实体在地面行走且不骑乘时,LivingEntity#onChangedBlock会调用EnchantmentHelper#runLocationChangedEffects。 Enchantment#runLocationChangedEffects维护激活状态并在条件满足时执行ReplaceDisk。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
详细生效链路
- 注册时不写数值效果,只写入特殊组件
PREVENT_ARMOR_CHANGE。 - 玩家尝试把手中物品与装备槽互换时,
Equippable#swapWithEquipmentSlot会检查当前装备。 - 若当前装备存在
PREVENT_ARMOR_CHANGE且玩家不是创造模式,则交换被拒绝。 - 其他生物尝试替换装备时也会通过
EnchantmentHelper.has(item, PREVENT_ARMOR_CHANGE)进行保护判断。 - 它属于
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
详细生效链路
- 注册
LOCATION_CHANGED,实体站在灵魂疾行方块上移动时激活。 - 激活后用
EnchantmentAttributeEffect临时添加MOVEMENT_SPEED和MOVEMENT_EFFICIENCY。 - 当条件不再满足时,
Enchantment#runLocationChangedEffects调onDeactivated把临时属性移除。 - 另一个
LOCATION_CHANGED效果带随机概率,会执行ChangeItemDamage(1),因此靴子会磨损。 - 此外还有两个
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
详细生效链路
- 注册
ATTRIBUTES:Attributes.SNEAKING_SPEED,每级+0.15F。 - 装备时
ItemStack#forEachModifier会向实体属性系统追加附魔提供的AttributeModifier。 EnchantmentHelper#forEachModifier根据装备槽位筛出匹配的附魔属性效果。- 玩家潜行和爬行移动速度逻辑读取
SNEAKING_SPEED属性。 - 因此迅捷潜行是长期属性型附魔,没有额外 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
详细生效链路
- 注册
DAMAGE,数值为AddValue(LevelBasedValue.perLevel(1.0F, 0.5F))。 - 玩家近战时
ServerPlayer#getEnchantedDamage调EnchantmentHelper#modifyDamage;普通生物近战时Mob#doHurtTarget也调同一个 helper。 - helper 遍历武器附魔并调用
Enchantment#modifyDamage。 modifyDamage最终走modifyDamageFilteredValue(DAMAGE, ...),把锋利的增伤叠加到基础伤害。- 锋利与亡灵杀手、节肢杀手、穿刺、致密、破甲同在
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
详细生效链路
- 注册
DAMAGE,每级+2.5F。 - 该效果带实体条件:目标必须属于
EntityTypeTags.SENSITIVE_TO_SMITE。 - 玩家或生物攻击时都通过
EnchantmentHelper#modifyDamage进入统一增伤链。 Enchantment#modifyDamageFilteredValue用ENCHANTED_DAMAGE上下文校验目标类型是否匹配。- 只有亡灵类目标满足条件时才会追加伤害。
关键代码展示(逐行注释)
// 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
详细生效链路
- 第一条链是
DAMAGE:对EntityTypeTags.SENSITIVE_TO_BANE_OF_ARTHROPODS每级+2.5F。 - 第二条链是
POST_ATTACK:攻击成功后,如果伤害是 direct 且目标仍是节肢目标,则触发附加效果。 - 攻击后的附魔效果由
EnchantmentHelper#doPostAttackEffects分发到Enchantment#doPostAttack。 - 执行器
ApplyMobEffect会随机时长/倍率地给目标附加MobEffects.SLOWNESS。 - 因此额外伤害和缓慢效果分别落在
modifyDamage与doPostAttackEffects两条链路上。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
KNOCKBACK,每级AddValue(1.0F)。 - 近战攻击计算击退时,
LivingEntity#getKnockback调EnchantmentHelper#modifyKnockback。 - helper 遍历武器附魔,
Enchantment#modifyKnockback读取KNOCKBACK组件并修改值。 - 返回的击退值继续传入
causeExtraKnockback。 - 所以该附魔只影响近战击退距离,不改变直接伤害数值。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
POST_ATTACK,enchanted=ATTACKER,affected=VICTIM,执行器为Ignite。 - 攻击成功后,玩家
itemAttackInteraction或生物Mob#doHurtTarget会调用EnchantmentHelper#doPostAttackEffects。 - 条件要求
DamageSource为直接伤害。 Ignite#apply会先触发 Bukkit combust 事件,未取消时调用Entity#igniteForSeconds让目标着火。- 同时它还被放进
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
详细生效链路
- 注册
EQUIPMENT_DROPS,攻击者为玩家时对受害者装备掉落概率每级+0.01F。 - 生物死亡掉装备时
Mob#dropCustomDeathLoot调EnchantmentHelper#processEquipmentDropChance。 - 该 helper 会分别遍历死者与攻击者装备,按
TargetedConditionalEffect规则修改装备掉落概率。 - 普通实体战利品数量/概率则由 loot function
EnchantedCountIncreaseFunction和LootItemRandomChanceWithEnchantedBonusCondition读取抢夺等级。 - 所以抢夺同时影响装备掉落和战利品表数量,是组件链和战利品旁路并存的附魔。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
ATTRIBUTES组件,为Attributes.SWEEPING_DAMAGE_RATIO写入一个随等级增长的分数值。 - 该属性修饰符在武器作为主手装备时,经
ItemStack#forEachModifier→EnchantmentHelper#forEachModifier挂到玩家属性集。 - 玩家近战命中后,
Player#attack在满足横扫判定时进入Player#doSweepAttack(Entity,float,DamageSource,float)(net/minecraft/world/entity/player/Player.java:1197)。 - 该方法在
net/minecraft/world/entity/player/Player.java:1200读取Attributes.SWEEPING_DAMAGE_RATIO,计算1.0F + ratio * baseDamage作为横扫伤害。 - 随后附近实体逐个受到横扫伤害,并继续进入
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
详细生效链路
- 注册
ATTRIBUTES组件,对Attributes.MINING_EFFICIENCY施加new LevelBasedValue.LevelsSquared(1.0F),也就是等级平方加成。 - 当工具在主手生效时,这个属性修饰符通过附魔属性遍历挂到玩家实体属性上。
- 玩家计算挖掘速度时,
Player#getDestroySpeed在net/minecraft/world/entity/player/Player.java:632把this.getAttributeValue(Attributes.MINING_EFFICIENCY)加到最终速度。 - 这个最终速度再参与方块破坏进度计算,因此效率附魔影响的是每 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; // 额外施加空中惩罚
}
}
完整注册源码
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
详细生效链路
- 注册中唯一直接写入的组件是
BLOCK_EXPERIENCE,用SetValue(0.0F)把挖矿经验清零,并与MINING_EXCLUSIVE(时运)互斥。 - 方块掉经验时,
Block#popExperience路径在net/minecraft/world/level/block/Block.java:660调EnchantmentHelper#processBlockExperience,该 helper 会把精准采集的SetValue应用到经验值上。 - “掉方块本体而不是普通掉落”不是在
Enchantment子类里硬编码,而是由战利品表生成器完成:BlockLootSubProvider#hasSilkTouch(net/minecraft/data/loot/BlockLootSubProvider.java:87)和createSilkTouchDispatchTable(:147)会根据工具附魔等级切换掉落分支。 - 原版具体方块在
VanillaBlockLoot中大量使用这条分发表,例如createSingleItemTableWithSilkTouch、dropWhenSilkTouch、otherWhenSilkTouch(如net/minecraft/data/loot/packs/VanillaBlockLoot.java:730、:1218、:1512)。 - 除掉落表外,若附魔被打上特定标签,还会阻止额外副作用:蜂巢放蜂
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
详细生效链路
- 注册两个
ITEM_DAMAGE效果:盔甲分支与非盔甲分支分别使用不同的RemoveBinomial概率公式。 - 任何物品需要扣耐久时,
ItemStack#hurtAndBreak会在net/minecraft/world/item/ItemStack.java:669进入EnchantmentHelper#processDurabilityChange(ServerLevel,ItemStack,int):int。 - helper 遍历物品附魔,把待扣减的耐久传入
Enchantment#modifyItemDamage;RemoveBinomial会按等级随机移除一部分应扣耐久。 - 返回值是“实际要扣的耐久数”,随后
ItemStack才真正更新 damage value,所以耐久附魔本质上是提前拦截并缩减损耗。 - 由于盔甲和工具走的是两套概率参数,所以同等级下盔甲耐久与工具耐久的保值率并不完全相同。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册块本身没有
effects组件,只声明了与精准采集互斥;因此时运主要通过战利品系统旁路生效。 - 方块掉落构建
LootContext时会把工具放进LootContextParams.TOOL,随后ApplyBonusCount#run在net/minecraft/world/level/storage/loot/functions/ApplyBonusCount.java:63读取工具上的时运等级。 - 读取点在
ApplyBonusCount.java:66,然后根据不同公式执行ore_drops、uniform_bonus_count或binomial_with_bonus_count计算新掉落数量。 - 若掉落表需要“随时运提升触发概率”而不是直接增量,则
BonusLevelTableCondition#test在net/minecraft/world/level/storage/loot/predicates/BonusLevelTableCondition.java:37读取同一个附魔等级决定概率。 - 原版方块掉落生成器
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
详细生效链路
- 注册
DAMAGE组件,条件要求LootContext.EntityTarget.DIRECT_ATTACKER是EntityTypeTags.ARROWS,数值为每级+1.0F,首级起始偏置为0.5F。 - 弓或弩射出的箭命中实体时,
AbstractArrow#onHitEntity在net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:467调EnchantmentHelper#modifyDamage(serverLevel,this.getWeaponItem(),entity,damageSource,arrowDamage)。 - helper 遍历发射武器上的附魔,再由
Enchantment#modifyDamage检查DIRECT_ATTACKER是否为箭实体;力量满足条件时把伤害加到MutableFloat。 - 返回的
arrowDamage会继续走entity.hurtOrSimulate(...),因此力量直接改的是箭实体的命中伤害,而不是发射时的初速度。 - 因为条件看的是直接攻击者是否为箭,所以该效果能覆盖普通箭、药箭、光灵箭等箭实体,只要发射武器本身带有力量附魔。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
KNOCKBACK组件,条件同样要求DIRECT_ATTACKER是箭实体,每级AddValue(1.0F)。 - 箭命中活体后,
AbstractArrow#doKnockback会在net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:563调EnchantmentHelper#modifyKnockback。 - helper 遍历发射武器附魔,
Enchantment#modifyKnockback命中PUNCH后把击退值累计到结果里。 - 最终修改后的击退量被用来推动目标,因此冲击只改变位移,不改变箭本身造成的生命值伤害。
- 与力量一样,它依赖的是“箭命中时回查发射武器附魔”,所以效果落点在命中阶段而不是发射阶段。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
PROJECTILE_SPAWNED效果,执行器为Ignite(LevelBasedValue.constant(100.0F)),即投射物生成时点燃 100 tick。 - 投射物真正入世界后,
Projectile#applyOnProjectileSpawned(ServerLevel,ItemStack)在net/minecraft/world/entity/projectile/Projectile.java:253调用EnchantmentHelper#onProjectileSpawned。 - helper 会把发射武器的附魔逐个交给
Enchantment#onProjectileSpawned;火矢命中时,Ignite#apply负责给箭实体设置燃烧时间。 - 之后燃烧中的箭在命中实体时会带出着火效果,因此火矢的触发时点是“生成箭”而不是“箭击中人”。
- 该附魔不直接增加数值伤害,伤害变化来自后续燃烧状态和实体受火逻辑。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
AMMO_USE组件,并用MatchTool.toolMatches(... Items.ARROW)限制只对普通箭生效,同时与弓系互斥集中的其他附魔保持原版兼容规则。 - 武器装填弹药时,
ProjectileWeaponItem#useAmmo在net/minecraft/world/item/ProjectileWeaponItem.java:139调EnchantmentHelper#processAmmoUse(serverLevel,weapon,projectile,1)。 - helper 遍历武器附魔后,
INFINITY的SetValue(0.0F)会把本次应消耗的箭数改成 0。 useAmmo随后走ammoToUse <= 0分支,创建一个copyWithCount(1)的临时箭堆并标记INTANGIBLE_PROJECTILE,这样能发射但不扣背包里的真实普通箭。- 由于谓词只匹配
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
详细生效链路
- 注册
FISHING_LUCK_BONUS,每级AddValue(1.0F)。 - 玩家使用鱼竿时,
FishingRodItem#use在net/minecraft/world/item/FishingRodItem.java:48调EnchantmentHelper#getFishingLuckBonus(serverLevel,itemStack,player)取附魔加成。 - 这个值被传进
new FishingHook(player, level, luck, lureSpeed)(FishingRodItem.java:49),鱼钩实体在构造时保存到字段luck。 - 真正抽取鱼获时,
FishingHook#retrieve在net/minecraft/world/entity/projectile/FishingHook.java:517把this.luck + owner.getLuck()写入LootParams.Builder#withLuck(...)。 - 因此海之眷顾不是直接改掉落表,而是提高 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
详细生效链路
- 注册
FISHING_TIME_REDUCTION,每级AddValue(5.0F)。 - 鱼竿使用时,
FishingRodItem#use在net/minecraft/world/item/FishingRodItem.java:47调EnchantmentHelper#getFishingTimeReduction(...),再乘以20.0F变成 tick 数。 - 得到的
lureSpeed被写进FishingHook构造参数,鱼钩实例保存在字段lureSpeed。 - 鱼钩等待鱼上钩时,
FishingHook#resetTimeUntilLured在net/minecraft/world/entity/projectile/FishingHook.java:423-424用this.lureSpeed直接减少随机等待时间;计时过程中timeUntilLured也按加速后的值递减。 - 所以饵钓作用的是“缩短咬钩前等待时间”,并不改变最终抽到哪一类战利品。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
TRIDENT_RETURN_ACCELERATION,每级AddValue(1.0F)。 - 投掷三叉戟创建实体时,
ThrownTrident构造函数在net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:47调this.getLoyaltyFromItem(tridentItem)初始化同步数据。 getLoyaltyFromItem在ThrownTrident.java:222-224调EnchantmentHelper#getTridentReturnToOwnerAcceleration(serverLevel,tridentItem,this),把附魔值换算成返回加速度。- 三叉戟 tick 时,
ThrownTrident#tick在ThrownTrident.java:73-90检查 loyalty 值;若已命中或进入 noPhysics,就按该值增加朝向持有者的速度。 - 等级越高,
accel = 0.05 * loyalty越大,回收越快;同时tickDespawn在ThrownTrident.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
详细生效链路
- 注册
DAMAGE组件,条件要求受击实体匹配EntityTypeTags.SENSITIVE_TO_IMPALING,每级额外+2.5F。 - 投掷命中时,
ThrownTrident#onHitEntity在net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:141调EnchantmentHelper#modifyDamage(serverLevel,this.getWeaponItem(),entity,damageSource,dmg)。 - 若三叉戟作为近战武器使用,则近战总伤害链也会在
LivingEntity.java:3363通过同一个modifyDamagehelper 读取附魔。 - helper 遍历三叉戟上的附魔,由
Enchantment#modifyDamage根据受害者是否属于SENSITIVE_TO_IMPALING决定是否叠加伤害。 - 最终加成后的
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
详细生效链路
- 注册两个 special effect:
TRIDENT_SPIN_ATTACK_STRENGTH与TRIDENT_SOUND,并与RIPTIDE_EXCLUSIVE(忠诚/引雷侧)互斥。 - 玩家松开右键时,
TridentItem#releaseUsing在net/minecraft/world/item/TridentItem.java:71调EnchantmentHelper#getTridentSpinAttackStrength(itemStack, player)。 - helper 遍历三叉戟附魔后,把激流等级换算成冲刺强度;同一方法在
TridentItem.java:76还会通过pickHighestLevel(... TRIDENT_SOUND)选取对应音效。 - 若强度大于 0 且玩家在水中或雨中,
releaseUsing走旋转冲刺分支,把玩家沿朝向发射出去并执行旋转攻击。 - 相反,
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
详细生效链路
- 注册两条效果链:
POST_ATTACK(命中实体)与HIT_BLOCK(命中方块);二者执行器都是SummonEntityEffect(LIGHTNING_BOLT)+PlaySoundEffect。 - 三叉戟命中实体后,
ThrownTrident#onHitEntity在net/minecraft/world/entity/projectile/arrow/ThrownTrident.java:150-153调EnchantmentHelper#doPostAttackEffectsWithItemSourceOnBreak(...)。 - 进入
POST_ATTACK链后,引雷要求同时满足:世界雷暴、受击实体位置可见天空、DIRECT_ATTACKER是三叉戟;满足后才召出闪电。 - 三叉戟命中方块时,
ThrownTrident#hitBlockEnchantmentEffects在ThrownTrident.java:168-179调EnchantmentHelper#onHitBlock,随后走HIT_BLOCK组件分发。 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
详细生效链路
- 注册两个数值组件:
PROJECTILE_COUNT +2与PROJECTILE_SPREAD +10。 - 弩装填时,
ProjectileWeaponItem#draw在net/minecraft/world/item/ProjectileWeaponItem.java:122-125通过EnchantmentHelper#processProjectileCount(serverLevel,weapon,shooter,1)算出要装填的投射物数量。 - 多重射击把数量从 1 改到 3;随后
draw循环里只有第一发走正常弹药消耗,额外两发会通过forceInfinite/ 临时复制堆的方式生成。 - 真正发射时,
ProjectileWeaponItem#shoot在ProjectileWeaponItem.java:57-58再通过processProjectileSpread计算扩散角,把三发投射物分散开。 - 因此多重射击的链路分成“装填数量”和“发射散布”两段:前者决定会生成几发,后者决定三发之间的夹角。
关键代码展示(逐行注释)
// 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.MAINHAND与EquipmentSlotGroup.OFFHAND。 - 注册位置:
net/minecraft/world/item/enchantment/Enchantments.java:1118
详细生效链路
- 注册
CROSSBOW_CHARGE_TIMEspecial effect,每级-0.25F,并额外注册三档CROSSBOW_CHARGING_SOUNDS。 - 弩计算装填时长时,
CrossbowItem#getChargeDuration在net/minecraft/world/item/CrossbowItem.java:250调EnchantmentHelper#modifyCrossbowChargingTime(crossbow,user,1.25F)。 - helper 遍历附魔后,
Enchantment#modifyCrossbowChargeTime把 quick charge 的负值叠到基础装填时间上,得到更短的最终蓄力时长。 - 同一个物品的装填音效由
CrossbowItem#getChargingSounds在CrossbowItem.java:260通过pickHighestLevel(... CROSSBOW_CHARGING_SOUNDS)选出。 - 因此快速装填既改变数值时间,也改变客户端/服务端播放的装填声阶段。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
PROJECTILE_PIERCING,每级+1,并与多重射击同属CROSSBOW_EXCLUSIVE互斥集。 - 箭实体创建时,
AbstractArrow在net/minecraft/world/entity/projectile/arrow/AbstractArrow.java:123-125调EnchantmentHelper#getPiercingCount(serverLevel,firedFromWeapon,pickupItemStack)并设置setPierceLevel(...)。 - 这个
pierceLevel被同步到箭实体数据里,后续命中逻辑会一直读取。 - 命中实体时,
AbstractArrow#onHitEntity/ 后续穿透逻辑在AbstractArrow.java:471-480、:544等位置判断getPierceLevel() > 0,决定箭是否继续存在并记录已穿透实体。 - 因此穿透的真正生效点不是命中时临时再算,而是在投射物生成阶段就把“可穿透层数”写进箭实体状态。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
SMASH_DAMAGE_PER_FALLEN_BLOCK,每级AddValue(0.5F),并与其它伤害类重锤附魔共用DAMAGE_EXCLUSIVE互斥集。 - 重锤计算下砸附加伤害时,
MaceItem#getAttackDamageBonus在net/minecraft/world/item/MaceItem.java:115调EnchantmentHelper#modifyFallBasedDamage(level,attacker.getWeaponItem(),victim,damageSource,0.0F)。 - helper 遍历重锤附魔后,
Enchantment#modifyFallBasedDamage会读取SMASH_DAMAGE_PER_FALLEN_BLOCK组件,把“每下落一格增加多少伤害”累计进结果值。 MaceItem随后把这个每格增量乘以fallDistance,并加到下砸总伤害中。- 因此致密不直接写死一个最终伤害,而是修改“按下落距离换算伤害”的系数,坠得越高加成越大。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
ARMOR_EFFECTIVENESS,每级AddValue(-0.15F);负值意味着削弱护甲吸收比例。 - 受击方进入护甲减伤结算时,
CombatRules#getDamageAfterAbsorb在net/minecraft/world/damagesource/CombatRules.java:20-23取出source.getWeaponItem()并调用EnchantmentHelper#modifyArmorEffectiveness。 - helper 遍历攻击武器上的附魔,由
Enchantment#modifyArmorEffectiveness读取ARMOR_EFFECTIVENESS组件,对当前armorFraction做负向修正。 CombatRules再把修正后的护甲比例夹到0.0F~1.0F并换算成最终伤害倍率,所以破甲作用在“护甲吸收比例”这一步,而不是直接给伤害加值。- 结果就是目标护甲仍然参与结算,但其减伤效率被下调;等级越高,护甲对这次攻击的保护越弱。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
POST_ATTACK,enchanted = ATTACKER、affected = ATTACKER,执行器为ExplodeEffect;条件要求DIRECT_ATTACKER未飞行且下落距离至少1.5。 - 近战命中成功后,玩家与怪物都会在攻击链末尾调用
EnchantmentHelper#doPostAttackEffects(如LivingEntity.java:3381、Mob.java:1624)。 - helper 分发到
Enchantment#doPostAttack后,风爆的目标仍然是攻击者本人,所以效果不是打在受害者身上,而是打在挥锤者当前位置。 ExplodeEffect#apply在net/minecraft/world/item/enchantment/effects/ExplodeEffect.java:61-82调serverLevel.explode(...),使用风弹式粒子、音效和击退倍率配置。- 因此风爆的本质是“下砸命中后立刻在攻击者脚下触发一次受控爆炸”,把攻击者向上弹起,形成连跳或二段下砸机会。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
POST_PIERCING_ATTACK,执行器是AllOf.entityEffects(...),组合了ChangeItemDamage、ApplyExhaustion、ApplyEntityImpulse和PlaySoundEffect。 - 戳刺武器组件执行攻击时,
PiercingWeapon#attack在net/minecraft/world/item/component/PiercingWeapon.java:84调attacker.postPiercingAttack()。 LivingEntity#postPiercingAttack在net/minecraft/world/entity/LivingEntity.java:2068把流程转给EnchantmentHelper#doPostPiercingAttackEffects(serverLevel,this)。- helper 遍历当前武器附魔,
Enchantment#doPostPiercingAttack(net/minecraft/world/item/enchantment/Enchantment.java:308)检查条件后执行各个实体效果:扣 1 点耐久、按等级增加饥饿消耗、沿朝向施加冲量,并播放突进音效。 - 注册条件还额外限制了不可骑乘、不可鞘翅飞行、不可在水中,以及玩家至少要有足够饱食度,所以突进不是“任何戳刺都能白嫖位移”,而是带状态门槛的动作强化。
关键代码展示(逐行注释)
// 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
详细生效链路
- 注册
REPAIR_WITH_XP,数值效果为MultiplyValue(2.0F),表示每点经验可换算成更多耐久修复量。 - 经验球被玩家拾取时,
ExperienceOrb#repairPlayerItems在net/minecraft/world/entity/ExperienceOrb.java:380先通过EnchantmentHelper#getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, player, ItemStack::isDamaged)随机挑选一个带修补且已受损的装备。 - 选中后,
ExperienceOrb.java:383调EnchantmentHelper#modifyDurabilityToRepairFromXp(player.level(), itemStack, amount),helper 遍历该物品附魔,把REPAIR_WITH_XP效果应用到“本次经验最多能修多少耐久”上。 - 随后
ExperienceOrb.java:384-393计算本次实际修复值、触发PlayerItemMendEvent,并直接减少itemStack的 damage value;剩余经验再递归尝试继续修其他可修物品。 - 因此经验修补的关键不是在物品自己 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
详细生效链路
- 注册
PREVENT_EQUIPMENT_DROP,没有额外数值,语义就是“这件装备在死亡掉落阶段不要生成掉落物”。 - 玩家死亡清空背包前,
Player#dropEquipment在net/minecraft/world/entity/player/Player.java:606-607会检查EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP);命中后直接把该格物品移除而不掉出。 - 服务端玩家保留/掉落清单处理中,
ServerPlayer.java:1153与ServerPlayer.java:1204也会再次跳过带PREVENT_EQUIPMENT_DROP的物品。 - 普通生物和可装备实体的死亡掉落同样会做过滤,例如
Mob#dropCustomDeathLoot的net/minecraft/world/entity/Mob.java:1064、AbstractHorse.java:529、Allay.java:424。 - 所以消失诅咒不是“把掉落物生成后再删除”,而是在各类死亡掉落入口就直接拦截,令该物品既不进入掉落表也不落地。
关键代码展示(逐行注释)
// 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
);