标签: Minecraft

  • 使用Architectury Loom开发Minecraft 26.1的模组时得到Failed to find official mojang mappings for 26.1的错误

    简单来说

    Minecraft 26.1开始正式取消混淆,原来适用于有混淆的游戏版本的工具链需要更新。

    Architectury Loom需要把dev.architectury.loom换成dev.architectury.loom-no-remap插件,并修改版本号为1.14-SNAPSHOT,用来处理不带混淆的游戏版本。同时Architectury Plugin也需要升级到3.5-SNAPSHOT版本。这样就能正常处理不带混淆的游戏,但这一点不论是在Architectury的文档还是在arch loom GitHub页面的issues里都没有提到


    Minecraft不再混淆

    继19w36a发布官方的混淆映射表以后,Mojang在2025年10月29日宣布,从26.1-snapshot-1开始,Java版的源代码不再进行混淆,25w45a至1.21.11,Mojang同时发布已混淆和未混淆的文件,用来帮助社区进行过渡。

    Fabric Loom提供了一个net.fabricmc.fabric-loom-remap的插件变种,用来处理带混淆的游戏,旧的插件IDfabric-loom是它的别名;而net.fabricmc.fabric-loom则用于处理无混淆的版本。

    在移除混淆后,Loom的modImplementationmodRuntimeOnly等configuration已经不再需要,直接使用implementationruntimeOnly等就可以;remapJar的task也被删除,直接使用jar就可以;dependencies里也不再需要mappings的configuration了。

    Architectury Loom在一个月前开始合并Fabric Loom 1.14

    中国有句话叫“闷声大发财”。

    和Fabric Loom相似地,作为其Fork的Arch Loom也需要做出一些更改。或许是为了旧代码的兼容性,他们使用了dev.architectury.loom-no-remap这一插件ID用于不带混淆的游戏。可能是由于Arch Loom 1.14还没正式发布,loom-no-remap没有在任何相关文档中被提到,现在只有1.14-SNAPSHOT。但是Shedaniel在cloth-config的代码库里已经这样用了1,所以我觉得可以认为这一更改已经确定了,其他开发者可以如此进行迁移。

    Arch Loom的整体变更和Fabric Loom相似,按上面提到的修改就可以。

    除此之外还需要把architectury-plugin升级到3.5-SNAPSHOT版本,旧版本还尝试依赖remapJar的task,会导致运行时出错。同时,Arch Plugin还移除了namedElements,引用common项目的时候也不再需要指定configuration。


    qyl制作的基于Architectury Loom的多加载器模组项目模板已经更新,现在支持26.1,欢迎使用https://github.com/qyl27/architectury-loom-template

    1. https://github.com/shedaniel/cloth-config/commit/48614681f2b39740c1316247499c0cac2d92b524 ↩︎
  • 在MinecraftForge中,无法获取已移除的实体的Capability

    TL;DR:

    实体会在被移除的时候让所有的Capability失效,需要手动调用Entity#reviveCapsgetCapability,完成以后调用Entity#invalidateCaps恢复之前的状态。

    此前因为一些Bug导致在某些情况下即使不reviveCaps也能获取到,但Bug被修复以后就不能用了……


    一个Bug是Bug,多个Bug能Work,修一个就Break(

    在1.13(Forge 25.0),Forge存在实体(Entity)死亡(death)不会导致Capability失效的问题1,Lex推送了一个提交来修复它2,让Capabilities在实体被移除(remove)且不保存数据的时候失效(调用invalidateCaps()方法)。

    实体被移除不完全等于死亡(LivingEntity的死亡是被移除的原因之一),此外玩家跳进末地的返回传送门等情况,也会让实体被移除。因此Forge给实体类上Patch了一个remove(boolean keepData)方法,当keepData是false时才会失效Caps。

    在Forge的Capabilities系统中,Capability由CapabilityProvider持有,通过CapabilityProvider#getCapability方法获取,该方法返回一个Optional。实体就是一个CapabilityProvider,它有一个bool类型的失效标记,如果为true,则获取Capability必定得到一个空的Optional。

    玩家跳进返回传送门时,在代码里被视为通关游戏(wonGame)的重生(respawn),而非像是通过下界传送门或者去往末地那样的移动(travelDimension)。前者会导致玩家实体(ServerPlayer)重生,也就是跳进返回传送门的玩家和在复活点生成的玩家不是同一个对象,虽然没有死亡,但也被移除了,有持久化需求的Capability要在新旧玩家实体之间复制。此时keepData是true,所以Capability仍然有效,以至于相安无事。


    在1.16.5(Forge 36.0),Forge引入了一个新的事件——LivingConversionEvent来代表一个实体变成另一个实体的情况3。这个事件有Pre和Post的变种,前者能够取消或者拿到新实体的EntityType,后者可以拿到新的实体对象。但在Post事件被抛出的时候,并不保证转换前的实体仍然有效。例如:村民转变成僵尸村民时无效——原实体先被移除再抛出事件;而村民转变为女巫的时候有效——抛出事件后再移除原实体。

    此时问题就初现端倪了:LivingEvtity被移除之后,getCapability会拿到一个空的Optional,即使实体仍然持有这个Caps的数据。因此村民变成僵尸村民的时候,直接从实体里拿不到Capability。但是由于村民一定是被杀死后才会变成僵尸村民,听上去也符合直觉。


    在1.17.1(Forge 37.1),由于mojang实体移除机制发生变更,Forge移除了带有keepData参数的Entity#remove方法,现在实体移除时,一律会让实体的Caps失效,如果模组作者想要拿已经移除之实体的Caps,要先调用Entity#reviveCaps(),获取到之后再用Entity#invalidateCaps()使其失效。

    这本来会造成复制玩家Caps的用例发生错误——跳进返回传送门也会导致Caps失效,但由于版本迁移过程中Patch的行号发生偏移,导致调用invalidateCaps方法的那一行Patch被打到实体类里面的别的方法上了4,所以问题并未发生,也没人注意到这个问题。


    直到1.19.1(Forge 41.1),有人修复了Patch里行号的偏移5。对跳进末地返回传送门的玩家实体来说,reviveCaps和invalidateCaps成为了必须的步骤,而不知道这件事的模组作者就要面对玩家从末地回来以后数据消失奇怪的bug了(x


    1. https://github.com/MinecraftForge/MinecraftForge/issues/5307 ↩︎
    2. https://github.com/MinecraftForge/MinecraftForge/commit/e6a73ef36c1bdfb0053c2c122f1c71d376d44651 ↩︎
    3. https://github.com/MinecraftForge/MinecraftForge/commit/b64f4780c5f951da2eb46aed78590cdbb3220700 ↩︎
    4. https://github.com/MinecraftForge/MinecraftForge/commit/9ec1e24dc510875263c0a5a5070bb61b3b4833c7 ↩︎
    5. https://github.com/MinecraftForge/MinecraftForge/commit/0b1b3c68fa527c30006e1bfbf69eecccf311ef34 ↩︎