项目

引擎模组

这是进阶且特殊的层级:替换游戏本身某一部分的模组。几乎所有模组都用不到。

你需要它吗?

几乎肯定不需要。用 CraftScript 或 Kotlin 基于 Crafting API 编写的模组可以涵盖方块、物品、生物、世界、界面和事件,并且在 Minecraft 更新后依然可用。引擎模组只用于替换游戏本身的一部分,例如更快的区块渲染器或新的光照引擎。如果你的想法能用普通 API 实现,就用普通 API。

它提供什么,代价是什么

模组的代码可以使用游戏自己的类,并用 mixin 对其打补丁。代价是:它只为某一个确切的 Minecraft 版本制作,只能在该版本上运行,作者必须为每个游戏版本更新它。它所使用的一切都没有兼容性承诺。

声明

在 crafting.mod.json 中添加 engine 部分,列出 mixin 配置:

crafting.mod.jsonJSON
{
  "id": "brandengine",
  "name": "Brand Engine",
  "version": "1.0.0",
  "game": "26.3",
  "entrypoints": ["com.example.engine.BrandEngine"],
  "engine": { "mixins": ["brandengine.mixins.json"] }
}

game 必须是确切的版本,例如 26.3,而不是范围。在其他版本上模组不会加载,游戏会说明原因。

独占部分

游戏的某些部分只能有一个替代者。模组通过 slots 声明占用:

crafting.mod.jsonJSON
{ "engine": { "slots": ["chunk_renderer"] } }
插槽 替换的部分
chunk_renderer 区块渲染器
lighting 光照引擎
shaders 着色器管线

每个部分只能由一个模组替换。如果两个模组都尝试,第二个不会加载,模组界面会显示是哪个模组占用了它。占用 shaders 的模组会关闭光影包。

在代码中

引擎功能需要明确选择启用,以免被意外使用:

BrandEngine.ktKotlin
@OptIn(CraftingInternal::class)
class BrandEngine : CraftingMod {
    override fun onLoad(ctx: ModContext) {
        Crafting.events.on<ServerStartedEvent> { e ->
            val server = Engine.handle(e.server) as MinecraftServer
            ctx.logger.info("Server brand: ${server.serverModName}")
        }
    }
}

Engine.handle(view) 返回 Crafting 玩家、世界、实体或服务器背后的游戏自身对象。

Mixin

Mixin 用 Java 编写,用来给游戏的类打补丁:

ServerBrandMixin.javaJava
@Mixin(MinecraftServer.class)
public abstract class ServerBrandMixin {
    @Inject(method = "getServerModName", at = @At("RETURN"), cancellable = true)
    private void brand(CallbackInfoReturnable<String> cir) {
        cir.setReturnValue(cir.getReturnValue() + "+brandengine");
    }
}

它的配置 brandengine.mixins.json 列出这些 mixin:

brandengine.mixins.jsonJSON
{ "required": true, "package": "com.example.engine.mixin", "compatibilityLevel": "JAVA_25",
  "mixins": ["ServerBrandMixin"], "injectors": { "defaultRequire": 1 } }

构建

针对游戏 jar 和 Mixin 库编译,两者均为 compile-only。Java 和 Kotlin 的目标版本为 25。

玩家看到什么

模组界面会标记引擎模组:“直接使用游戏,仅为 Minecraft 26.3 制作:游戏更新可能使其失效”,并显示每个模组替换的部分。