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

Fabric模组开发:程序化注册方块时遇「无法获取属性」错误

问题描述

开发Fabric模组时,为原版几乎所有方块添加「开裂」「苔藓化」等变体,采用循环批量注册的方式(变体名称格式为变体名+原方块名,比如Cracked Oak Planks),流程可正常生成模型文件,但在继承原方块硬度、材质等属性时遇到问题:针对原木、红石矿石等带子类特有属性的方块注册变体时抛出错误。

问题代码

public static void registerModBlocks() {
        for (Field block : Blocks.class.getFields()) {
             Block blockObject = (Block) block.get(null);

             TutorialMod.LOGGER.info(block.getName());

             Block settings = new Block(FabricBlockSettings.copyOf(blockObject));

             String blockName = "cracked_" + block.getName().toLowerCase();
             gen_blocks.put(blockName, registerBlock(blockName, settings, ModItemGroup.ITEM_GROUP));


        }
    }
}

错误信息

  • 原木报错:
Cannot get property EnumProperty{name=axis, clazz=class net.minecraft.util.math.Direction$Axis, values=[x, y, z]} as it does not exist in Block{minecraft:air}
  • 红石矿石报错:
Cannot get property BooleanProperty{name=lit, clazz=class java.lang.Boolean, values=[true, false]} as it does not exist in Block{minecraft:air}

错误原因明确:原木的axis、红石矿石的lit属于Block子类的特有属性,统一用Block类创建变体无法继承这些属性。


解决方案

核心思路是通过类型判断生成对应子类的变体方块,而非统一使用基础Block类,同时过滤掉不需要生成变体的功能方块,无需额外维护JSON标签。

修改后的代码示例

public static void registerModBlocks() {
    for (Field blockField : Blocks.class.getFields()) {
        try {
            Block originalBlock = (Block) blockField.get(null);
            String originalBlockName = blockField.getName().toLowerCase();
            TutorialMod.LOGGER.info("Processing block: {}", originalBlockName);

            // 跳过功能方块(可根据需求自行扩展排除列表)
            if (isFunctionBlock(originalBlock)) {
                continue;
            }

            Block variantBlock;
            String variantName = "cracked_" + originalBlockName;

            // 根据原方块的实际类型创建对应变体
            if (originalBlock instanceof PillarBlock) {
                // 处理原木、石英柱等带axis属性的方块
                variantBlock = new PillarBlock(FabricBlockSettings.copyOf(originalBlock));
            } else if (originalBlock instanceof RedstoneOreBlock) {
                // 处理红石矿石(带lit属性)
                variantBlock = new RedstoneOreBlock(FabricBlockSettings.copyOf(originalBlock));
            } else if (originalBlock instanceof OreBlock) {
                // 处理普通矿石方块
                variantBlock = new OreBlock(FabricBlockSettings.copyOf(originalBlock));
            } else if (originalBlock instanceof SlabBlock) {
                // 处理台阶方块
                SlabBlock originalSlab = (SlabBlock) originalBlock;
                variantBlock = new SlabBlock(FabricBlockSettings.copyOf(originalBlock));
            } else {
                // 默认处理普通方块
                variantBlock = new Block(FabricBlockSettings.copyOf(originalBlock));
            }

            // 注册变体方块
            gen_blocks.put(variantName, registerBlock(variantName, variantBlock, ModItemGroup.ITEM_GROUP));

        } catch (IllegalAccessException e) {
            TutorialMod.LOGGER.error("Failed to process block: {}", blockField.getName(), e);
        }
    }
}

// 辅助方法:判断是否为不需要生成变体的功能方块
private static boolean isFunctionBlock(Block block) {
    // 可自行添加更多需要排除的方块类型,比如门、按钮、压力板等
    return block instanceof DoorBlock || block instanceof ButtonBlock || block instanceof PressurePlateBlock
            || block instanceof TrapdoorBlock || block instanceof LeverBlock || block instanceof RedstoneWireBlock;
}

关键说明

  1. 类型匹配创建变体:通过instanceof判断原方块的子类类型,创建对应类型的变体方块,确保继承子类特有的属性和行为(比如PillarBlock的axis方向、RedstoneOreBlock的发光逻辑)。
  2. 过滤功能方块:通过isFunctionBlock方法跳过不需要生成变体的功能方块,避免无效注册和逻辑冲突。
  3. 异常捕获:添加IllegalAccessException捕获,防止单个方块处理失败导致整个注册流程崩溃。

额外建议

  • 可扩展更多方块类型的判断逻辑,比如楼梯(StairsBlock)、栅栏(FenceBlock)等,保证变体方块的行为与原方块一致。
  • 测试时重点验证特殊方块变体的加载状态,比如原木的朝向切换、红石矿石的发光效果。
  • 若需添加「苔藓化」等其他变体,可将变体类型(cracked、mossy)抽离为参数,复用注册逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:53:09