使用 Mixin

注解

此页适用于 SpongeCommon、 SpongeForge 和 SpongeVanilla。这三个仓库利用 Mixin 挂钩到底层进行实现 (原版 Minecraft 服务器和 Forge 服)。

Mixins是一种在运行时修改Java代码的方式,它向类中添加额外的行为。这可以将我们需要的功能加入到原版的Minecraft中去。Mixins对于Sponge的运行来说是必须的。

Mixin Wiki 上对一些关于Mixin使用的核心概念进行了基本的介绍。

上面的Wiki相当基础,如果你是一位有经验的Java开发者,你可以跳过第4节,其中讨论了mixins本身。

如果你打算开始使用 Mixin,我们强烈推荐你先仔细研究在 SpongeForge 的代码仓库 中的所有例子。它们都有良好的注释并且包含了更多高级的用法。你也可以参考 Mixin 本身的 Javadoc,几乎所有的东西都已有对应的文档。

警告:使用 Mixin 时请注意,不能在 Mixin 中使用任何匿名类或 lambda 表达式。

这意味着像后面的一些代码会搞坏mixin,同时也会把Sponge搞到万劫不复的境地。

return new Predicate<ItemStack>() {
    @Override
    public boolean test(ItemStack input) {
        return input.getItem().equals(Items.golden_apple);
    }
}
return input -> input.getItem().equals(Items.golden_apple);
return this::checkItem;

这适用于所有带 @Mixin 注解的类。不被 Mixin 处理器访问的类可以使用这些功能。然而,你可以在一个静态的实用程序类中创建匿名类;如此一来,实用程序类在运行时中仍然存在,而 Mixin 类将合并到指定的目标类中。因此,下面的代码可以工作。

public class ItemUtil {
    public static Predicate<ItemStack> typeChecker(final Item item) {
        return new Predicate<ItemStack>() {
            @Override
            public boolean test(ItemStack input) {
                return input.getItem().equals(item);
            }
        }
    }
}

@Mixin(TargetClass.class)
public abstract class SomeMixin {
    public Predicate<ItemStack> someFunction() {
        return ItemUtil.typeChecker(Items.golden_apple);
    }
}

注解

不仅是 Sponge,还有很多项目也在使用 Mixin。所以 Mixin 有其自己的文档。