项目
引擎模组
这是进阶且特殊的层级:替换游戏本身某一部分的模组。几乎所有模组都用不到。
你需要它吗?
几乎肯定不需要。用 CraftScript 或 Kotlin 基于 Crafting API 编写的模组可以涵盖方块、物品、生物、世界、界面和事件,并且在 Minecraft 更新后依然可用。引擎模组只用于替换游戏本身的一部分,例如更快的区块渲染器或新的光照引擎。如果你的想法能用普通 API 实现,就用普通 API。
它提供什么,代价是什么
模组的代码可以使用游戏自己的类,并用 mixin 对其打补丁。代价是:它只为某一个确切的 Minecraft 版本制作,只能在该版本上运行,作者必须为每个游戏版本更新它。它所使用的一切都没有兼容性承诺。
声明
在 crafting.mod.json 中添加 engine 部分,列出 mixin 配置:
{
"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 声明占用:
{ "engine": { "slots": ["chunk_renderer"] } }| 插槽 | 替换的部分 |
|---|---|
chunk_renderer |
区块渲染器 |
lighting |
光照引擎 |
shaders |
着色器管线 |
每个部分只能由一个模组替换。如果两个模组都尝试,第二个不会加载,模组界面会显示是哪个模组占用了它。占用 shaders 的模组会关闭光影包。
在代码中
引擎功能需要明确选择启用,以免被意外使用:
@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 编写,用来给游戏的类打补丁:
@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:
{ "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 制作:游戏更新可能使其失效”,并显示每个模组替换的部分。