数据加载条件

数据加载条件

有时需要根据其他 Mod 是否存在、是否有 Mod 添加了某种矿石等条件,启用或禁用部分功能。NeoForge 为此提供数据加载条件。该系统最初用于配方,因此曾称为配方条件,后来扩展到了其他系统;这也解释了为何部分内置条件仍只适用于物品。

多数 JSON 文件可以在根对象中声明可选的 neoforge:conditions 区块,在实际加载数据前进行求值。当且仅当全部条件通过时才继续加载,否则忽略此文件。战利品表例外:条件不通过时会替换为空战利品表。

{
    "neoforge:conditions": [
        {
            // Condition 1
        },
        {
            // Condition 2
        },
        // ...
    ],
    // The rest of the data file
}

提示 如果加载的值不是映射/对象,应将其存储在 neoforge:value 中:

{
    "neoforge:conditions": [ /* ...*/ ],
    "neoforge:value": 2 // The value to load
}

例如,只在存在 ID 为 examplemod 的 Mod 时加载文件,可以这样写:

{
    // highlight-start
    "neoforge:conditions": [
        {
            "type": "neoforge:mod_loaded",
            "modid": "examplemod"
        }
    ],
    // highlight-end
    "type": "minecraft:crafting_shaped",
    // ...
}

提示 多数原版文件已通过 ConditionalCodec 包装器打补丁以支持条件。但并非所有系统都支持,尤其是不使用 codec 的系统。要确认文件是否支持条件,请检查其底层 codec 定义。

内置条件

neoforge:always 与 neoforge:never

不包含其他数据,分别始终返回真和假。

{
    // Will always return true (or false for "neoforge:never")
    "type": "neoforge:always"
}

建议 使用 neoforge:never 可以简洁地禁用数据文件。只需在目标位置放置以下内容的文件:

{"neoforge:conditions":[{"type":"neoforge:never"}]}

以此方式禁用文件不会产生大量日志。

neoforge:not

接收另一个条件,并反转其结果。

{
    // Inverts the result of the stored condition
    "type": "neoforge:not",
    "value": {
        // Another condition
    }
}

neoforge:and 与 neoforge:or

接收待运算的一个或多个条件,并应用对应逻辑。接收的条件数量没有限制。

{
    // ANDs the stored conditions together (or ORs for "neoforge:or")
    "type": "neoforge:and",
    "values": [
        {
            // First condition
        },
        {
            // Second condition
        }
    ]
}

neoforge:mod_loaded

指定 Mod ID 的 Mod 已加载时返回真,否则返回假。

{
    "type": "neoforge:mod_loaded",
    // Returns true if "examplemod" is loaded
    "modid": "examplemod"
}

neoforge:registered

指定注册表中,给定注册名的对象已经注册时返回真,否则返回假。

{
    "type": "neoforge:registered",
    // The registry to check the value for
    // Defaults to `minecraft:item`
    "registry": "minecraft:item",
    // Returns true if "examplemod:example_item" has been registered
    "value": "examplemod:example_item"
}

neoforge:tag_empty

指定注册表标签为空时返回真,否则返回假。

{
    "type": "neoforge:tag_empty",
    // The registry to check the tag for
    // Defaults to `minecraft:item`
    "registry": "minecraft:item",
    // Returns true if "examplemod:example_tag" is an empty tag
    "tag": "examplemod:example_tag"
}

neoforge:feature_flags_enabled

指定功能标志已启用时返回真,否则返回假。

{
    "type": "neoforge:feature_flags_enabled",
    // Returns true if the "examplemod:example_feature" is enabled
    "flags": [
        "examplemod:example_feature"
    ]
}

创建自定义条件

实现 ICondition 及其 #test(IContext),并创建对应的映射 codec,即可创建自定义条件。#test 的 IContext 参数可访问部分游戏状态,目前仅支持查询注册表标签。某些带条件的对象可能在标签之前加载,此时上下文为 IContext.EMPTY,不包含标签信息。

例如,实现一个 xor(异或)条件:

public record XorCondition(ICondition first, ICondition second) implements ICondition {
    public static final MapCodec<XorCondition> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
            ICondition.CODEC.fieldOf("first").forGetter(XorCondition::first),
            ICondition.CODEC.fieldOf("second").forGetter(XorCondition::second)
    ).apply(inst, XorCondition::new));

    @Override
    public boolean test(ICondition.IContext context) {
        return this.first.test(context) ^ this.second.test(context);
    }

    @Override
    public MapCodec<? extends ICondition> codec() {
        return CODEC;
    }
}

条件采用 codec 注册表,因此需要注册 codec:

public static final DeferredRegister<MapCodec<? extends ICondition>> CONDITION_CODECS =
        DeferredRegister.create(NeoForgeRegistries.Keys.CONDITION_CODECS, ExampleMod.MOD_ID);

public static final Supplier<MapCodec<XorCondition>> XOR =
        CONDITION_CODECS.register("xor", () -> XorCondition.CODEC);

随后即可在数据文件中使用此条件。假设它注册在 examplemod 命名空间下:

{
    "neoforge:conditions": [
        {
            "type": "examplemod:xor",
            "first": {
                // Either this condition is true
                "type": "..."
            },
            "second": {
                // Or this condition, not both!
                "type": "..."
            }
        }
    ],
    // The rest of the data file
}

数据生成

虽然数据包 JSON 文件可以使用加载条件,但只有少数数据提供器已适配生成这些条件,包括:

对于条件本身,NeoForgeConditions 为各内置条件提供静态辅助方法,返回对应的 ICondition。


来源: NeoForged/Documentation(26.1)。中文翻译依据提交 4a680cdd4d15。