You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fabric 1.21.1服务端模组:未注册药水能否添加多效酿造配方?

问题

开发仅服务端的Fabric 1.21.1模组,目标是添加带有原版效果的自定义药水,当前遇到核心矛盾:

  • 不注册新物品/药水时,无法配置有效的酿造配方
  • 注册新物品/药水后,原版客户端遇到该物品会被踢出,缺少对应注册表的Fabric客户端也无法加入服务器

最初尝试用builder.registerPotionRecipe(),但该方法需要RegistryEntry<Potion>而非自定义的Potion对象;改用builder.registerItemRecipe()后服务器启动失败,报错如下:

[17:10:46] [main/ERROR] (Minecraft) Failed to start the minecraft server
 java.lang.IllegalStateException: Some intrusive holders were not registered: [Reference{null=[unregistered]}, Reference{null=[unregistered]}]
    at net.minecraft.registry.SimpleRegistry.freeze(SimpleRegistry.java:359) ~[minecraft-common-c2b31d572c-1.21.1-net.fabricmc.yarn.1_21_1.1.21.1+build.3-v2.jar:?]
    at net.minecraft.registry.Registries.freezeRegistries(Registries.java:264) ~[minecraft-common-c2b31d572c-1.21.1-net.fabricmc.yarn.1_21_1.1.21.1+build.3-v2.jar:?]
    at net.minecraft.registry.Registries.bootstrap(Registries.java:248) ~[minecraft-common-c2b31d572c-1.21.1-net.fabricmc.yarn.1_21_1.1.21.1+build.3-v2.jar:?]
    at net.minecraft.server.Main.handler$zhp000$fabric-registry-sync-v0$afterModInit(Main.java:1547) ~[minecraft-common-c2b31d572c-1.21.1-net.fabricmc.yarn.1_21_1.1.21.1+build.3-v2.jar:?]
    at net.minecraft.server.Main.main(Main.java:111) [minecraft-common-c2b31d572c-1.21.1-net.fabricmc.yarn.1_21_1.1.21.1+build.3-v2.jar:?]
    at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:480) [fabric-loader-0.16.5.jar:?]
    at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:74) [fabric-loader-0.16.5.jar:?]
    at net.fabricmc.loader.impl.launch.knot.KnotServer.main(KnotServer.java:23) [fabric-loader-0.16.5.jar:?]
    at net.fabricmc.devlaunchinjector.Main.main(Main.java:86) [dev-launch-injector-0.2.1+build.8.jar:?]

原测试代码:

@Override
public void onInitializeServer() {
    ArrayList<StatusEffectInstance> RICH_POTION_EFFECTS = new ArrayList<>();
    RICH_POTION_EFFECTS.add(new StatusEffectInstance(StatusEffects.HERO_OF_THE_VILLAGE, 480, 5));
    RICH_POTION_EFFECTS.add(new StatusEffectInstance(StatusEffects.LUCK, 480, 3));
    Item RICH_POTION = new Item(new Item.Settings().component(DataComponentTypes.POTION_CONTENTS, new PotionContentsComponent(Optional.empty(),Optional.empty(), RICH_POTION_EFFECTS)));

    Item AWKWARD_POTION = new Item(new Item.Settings().component(DataComponentTypes.POTION_CONTENTS, new PotionContentsComponent(Potions.AWKWARD)));
        FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> {
            builder.registerItemRecipe(
                    AWKWARD_POTION,
                    Items.EMERALD_BLOCK,
                    RICH_POTION
            );
        });
}

虽然能看到酿造配方生效,但核心的客户端兼容性问题和服务器启动报错仍未解决,询问是否能在不注册新药水的前提下,创建带多种效果的药水并添加酿造配方。

解决方案

可以实现,核心思路是复用原版药水物品,通过数据组件动态注入自定义效果,完全不需要注册新的物品或药水,避免客户端兼容性问题:

关键原理

  • 原版客户端已经识别Items.POTION(以及喷溅、滞留药水等)这类物品,只要物品本身是已注册的原版条目,即使数据组件里的效果是自定义组合,客户端也能正常解析(因为效果都是原版的)
  • 之前的报错是因为创建了未注册的Item实例,Minecraft注册表冻结时会检查所有holder,未注册的实例会触发异常

修正后的代码

@Override
public void onInitializeServer() {
    // 定义自定义药水的效果组合
    List<StatusEffectInstance> richPotionEffects = List.of(
            new StatusEffectInstance(StatusEffects.HERO_OF_THE_VILLAGE, 480, 5),
            new StatusEffectInstance(StatusEffects.LUCK, 480, 3)
    );

    // 构建输出药水的组件:使用原版药水物品,注入自定义效果
    ItemStack outputPotion = new ItemStack(Items.POTION);
    outputPotion.set(DataComponentTypes.POTION_CONTENTS, new PotionContentsComponent(
            Optional.empty(),
            Optional.empty(),
            richPotionEffects
    ));

    // 注册酿造配方:输入用原版尴尬药水,原料用绿宝石块,输出为带自定义效果的原版药水
    FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> {
        builder.registerItemRecipe(
                Items.POTION, // 输入物品:原版药水
                stack -> stack.get(DataComponentTypes.POTION_CONTENTS)
                        .map(content -> content.potion().orElse(null) == Potions.AWKWARD)
                        .orElse(false), // 输入判断:必须是尴尬药水
                Items.EMERALD_BLOCK, // 酿造原料
                outputPotion // 输出:带自定义效果的原版药水栈
        );
    });
}

代码说明

  1. 复用原版物品:直接使用Items.POTION作为输入和输出的物品类型,避免创建未注册的Item实例
  2. 输入判断逻辑:通过lambda表达式筛选出是尴尬药水的Items.POTION栈,替代之前手动创建未注册的尴尬药水Item
  3. 动态效果注入:通过ItemStack.set()给原版药水栈添加自定义效果的PotionContentsComponent,客户端能正常识别这些原版效果
  4. 无注册表冲突:所有用到的物品和效果都是原版已注册的内容,不会触发客户端踢人或服务器注册表报错

额外注意事项

  • 如果需要喷溅/滞留版本的自定义药水,只需替换Items.POTION为Items.SPLASH_POTION或Items.LINGERING_POTION即可
  • 确保所有使用的StatusEffect都是原版已有的,避免客户端无法识别的自定义效果

内容的提问来源于stack exchange,提问作者SMGPDBGMCB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:57:15