跳至主要內容

Minecraft Forge Mod 开发手记——从零打造自定义物品

布衣云水客大约 4 分钟文章MinecraftForgeJava游戏开发

概要

作为一个程序员兼 Minecraft 玩家,迟早会走到这一步——自己写 Mod

本文记录了用 Minecraft Forge 1.20.6 开发一套自定义物品的过程:包括一个能探测钻石矿的探测器、一把带特效的美弓、一套终极盔甲,以及配套的成就系统和存档持久化。

不夸张地说,写 Minecraft Mod 是一种既能学 Java 又能玩得开心的学习方式

环境搭建

Forge 1.20.6 使用 MDK(Mod Development Kit),Gradle 构建:

forge-1.20.6-50.2.0-mdk/
├── src/main/java/zzzz/fmltutor/    # Mod 源码
├── src/main/resources/             # 资源文件(模型、纹理、语言)
├── build.gradle                    # Gradle 构建配置
└── gradlew.bat                     # Windows 构建脚本

核心依赖只需要 Forge 本身,构建命令:

.\gradlew.bat build        # 编译
.\gradlew.bat runClient    # 启动测试客户端

Mod 主类

每个 Forge Mod 的入口是一个带 @Mod 注解的类:

@Mod("fmltutor")
public class FMLTutor {
    public static final String MODID = "fmltutor";

    public FMLTutor(FMLJavaModLoadingContext context) {
        IEventBus modEventBus = context.getModEventBus();
        // 注册物品
        ModItems.ITEMS.register(modEventBus);
        // 注册事件处理器
        MinecraftForge.EVENT_BUS.register(new CraftingEventHandler());
    }
}

三个关键步骤:

  1. 物品注册——告诉游戏"我有这些新物品"
  2. 事件监听——在游戏事件发生时执行自定义逻辑
  3. 创造模式标签——让物品出现在创造模式物品栏

钻石探测器:最有"程序员味"的物品

这是我的得意之作——一个可以探测附近钻石矿的工具:

public class DiamondDetector extends Item {
    private static final double SUCCESS_CHANCE = 0.125;  // 12.5% 成功率
    private static final int SEARCH_RADIUS = 16;         // 搜索半径
    private static final int COOLDOWN_TICKS = 100;       // 5秒冷却

    @Override
    public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
        if (!level.isClientSide) {
            if (Math.random() < SUCCESS_CHANCE) {
                // 扫描 32×32×32 范围的所有方块
                List<BlockPos> diamonds = findDiamondOre(level, player.blockPosition());
                if (!diamonds.isEmpty()) {
                    // 找到!给出方向和距离
                    BlockPos nearest = findNearest(player.blockPosition(), diamonds);
                    int distance = (int) Math.sqrt(player.blockPosition().distSqr(nearest));
                    String direction = getDirection(player.blockPosition(), nearest);
                    player.sendSystemMessage(Component.literal(
                        "[Diamond Found!] " + direction +
                        " about " + distance + " blocks away, Y=" + nearest.getY()
                    ));
                }
            }
        }
    }
}

这个物品的设计体现了几个游戏机制知识:

机制实现作用
概率12.5% 成功率不会太强也不会太弱
冷却CooldownTicks = 100 (5秒)防止无脑连点
耐久durability(16)限制使用次数
音效反馈成功/失败不同音效增强沉浸感
方向指示计算东西南北+上下功能性强

最核心的方块扫描算法就是三重循环遍历:

for (int x = -16; x <= 16; x++)
    for (int y = -16; y <= 16; y++)
        for (int z = -16; z <= 16; z++)
            if (level.getBlockState(pos).is(Blocks.DIAMOND_ORE))
                diamonds.add(pos);

朴实无华,但确实能跑。在 16 格半径内约 35000 个方块的扫描,服务端处理没有明显卡顿。

美丽弓:继承 + 增强

基于原版弓的增强版:

public class BeautifulBow extends BowItem {
    public BeautifulBow() {
        super(new Properties().durability(500));  // 原版 384
    }

    @Override
    public AbstractArrow customArrow(AbstractArrow arrow) {
        // 箭附带发光效果——方便追踪
        arrow.addEffect(new MobEffectInstance(MobEffects.GLOWING, 200, 0));
        // 伤害提升 50%
        arrow.setBaseDamage(arrow.getBaseDamage() * 1.5);
        return arrow;
    }

    @Override
    public int getUseDuration(ItemStack stack) {
        return 15;  // 原版 20,更快的拉弓速度
    }
}

对比原版弓:

属性原版弓美丽弓
耐久384500
伤害1.0x1.5x
拉弓速度20 ticks15 ticks (快25%)
特效箭附带发光

合成成就系统

通过事件监听实现了"首次合成 Mod 物品时解锁成就":

@SubscribeEvent
public static void onItemCrafted(PlayerEvent.ItemCraftedEvent event) {
    // 检查合成的物品是否属于本模组
    if (craftedItem.getItem().getCreatorModId(craftedItem).equals("fmltutor")) {
        if (!data.hasPlayerCrafted(playerUUID)) {
            data.addPlayer(playerUUID);  // 持久化保存
            player.sendSystemMessage(Component.literal("恭喜!你解锁了答辩工艺!"));
        }
    }
}

关键是存档级别的持久化——使用 Minecraft 的 SavedData 机制:

public static class FmltutorCraftingData extends SavedData {
    private final Set<UUID> playersWhoCrafted = new HashSet<>();

    @Override
    public CompoundTag save(CompoundTag tag) { /* 序列化为 NBT */ }

    public static FmltutorCraftingData get(ServerLevel level) {
        // 自动从存档加载或创建
        return storage.computeIfAbsent(..., "fmltutor_crafting_data");
    }
}

这样即使退出重进、切换世界,每个玩家的合成记录都会被保留。

终极盔甲套装

一套满级防护盔甲,四个部位(头盔、胸甲、护腿、靴子),通过 LivingHurtEvent 事件实现特殊伤害减免逻辑。

开发心得

  1. Forge 事件系统非常强大——几乎所有游戏行为都有对应的事件可以监听和修改
  2. 客户端/服务端分离是核心概念——很多逻辑只在服务端执行(!level.isClientSide),忘记这个会导致各种奇怪 bug
  3. 物品注册的时机很重要——必须在 Mod 构造期间通过 DeferredRegister 注册,时机不对就不生效
  4. 模型和纹理需要 JSON 配置——models/item/textures/item/ 目录下的资源文件决定物品在游戏中的外观

小结

Minecraft Mod 开发是一个非常适合 Java 程序员的练手项目。它涉及的领域很广:

  • 事件驱动架构
  • 数据持久化(NBT)
  • 客户端/服务端通信
  • 资源管理和加载
  • 3D 渲染管线

而且最棒的是——你写的每一行代码,都能在游戏里亲眼看到效果。这种即时反馈是其他开发体验难以比拟的。


完整源码见 D:\workspace\project\forge\,运行 ./gradlew.bat runClient 即可体验。