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

使用DeferredRegistry的模组物品在Class Map中无法找到的问题求助

问题原因与解决方案

核心问题

你调用ModItems.SILVER_INGOT.get()时触发NPE,是因为RegistryObject的get()方法只有在物品完成注册后才能调用,而你大概率是在方块初始化(比如静态代码块、方块构造函数)阶段就调用了这个方法——此时DeferredRegistry还没完成模组物品的注册流程,RegistryObject里还没有实际的Item实例。

解决方案

1. 延迟配方Map的初始化

不要在静态代码块或方块构造阶段填充配方Map,而是在游戏注册流程完成后的事件中初始化,比如FMLCommonSetupEvent:

// 假设你的配方Map是类成员变量
private static final Map<Item, Item> RECIPE_MAP = new HashMap<>();

// 在模组主类或专门的事件处理类中注册监听
@SubscribeEvent
public static void onCommonSetup(FMLCommonSetupEvent event) {
    // 使用enqueueWork确保在主线程执行
    event.enqueueWork(() -> {
        // 此时所有物品已完成注册,可安全调用get()
        RECIPE_MAP.put(ModItems.SILVER_INGOT.get(), ModItems.SILVER_BRICK.get());
        // 原版物品可直接添加
        RECIPE_MAP.put(Items.STONE, Items.STONE_BRICKS);
    });
}

2. 直接用RegistryObject作为Map的键(可选)

如果不想延迟初始化,可以把配方Map的键类型换成RegistryObject<Item>,这样不需要提前调用get(),在onStep方法里再获取实例:

private static final Map<RegistryObject<Item>, RegistryObject<Item>> RECIPE_MAP = Map.of(
    ModItems.SILVER_INGOT, ModItems.SILVER_BRICK,
    RegistryObject.of(Items.STONE.getRegistryName(), Item.REGISTRY), Items.STONE_BRICKS
);

// 在onStep方法中处理时:
ItemEntity entity = ...;
Item inputItem = entity.getItem().getItem();
// 遍历Map找到匹配的RegistryObject
for (Map.Entry<RegistryObject<Item>, RegistryObject<Item>> entry : RECIPE_MAP.entrySet()) {
    if (entry.getKey().get() == inputItem) {
        Item outputItem = entry.getValue().get();
        // 执行合成逻辑
        break;
    }
}

这种方式全程依赖RegistryObject,避免了提前获取实例的风险。

3. 排查代码执行时机

检查你调用get()的代码是否在静态初始化阶段执行——比如方块类的静态代码块、静态成员变量的初始化表达式,这些都会在模组加载早期执行,此时DeferredRegistry的注册还未完成,必然会触发NPE。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:41:08