数据加载条件
有时需要根据其他 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 文件可以使用加载条件,但只有少数数据提供器已适配生成这些条件,包括:
RecipeProvider,通过RecipeOutput#withConditions,也包括配方进度。JsonCodecProvider及其子类SpriteSourceProvider。DataMapProvider。GlobalLootModifierProvider。DatapackBuiltinEntriesProvider,通过Map<ResourceKey<?>, List<ICondition>>参数。
对于条件本身,NeoForgeConditions 为各内置条件提供静态辅助方法,返回对应的 ICondition。
来源: NeoForged/Documentation(26.1)。中文翻译依据提交
4a680cdd4d15。