战利品表生成
构造新的 LootTableProvider 并提供 LootTableProvider$SubProviderEntry,即可为模组生成战利品表。必须将提供者添加到 DataGenerator。
原创说明图,依据 Forge 1.21.x 官方文档 绘制。
// 在模组事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
event.includeServer(), // 仅在生成服务端数据时运行
output -> new MyLootTableProvider(
output,
Collections.emptySet(), // 必须生成的表的注册名;也可留空
List.of(subProvider1, subProvider2, /*...*/) // 生成战利品的子提供者
)
);
}
LootTableSubProvider
每个 LootTableProvider$SubProviderEntry 接收一个提供的 LootTableSubProvider,针对给定 LootContextParamSet 生成战利品表。LootTableSubProvider 有一个方法,接收写入器(BiConsumer<ResourceLocation, LootTable.Builder>)来生成表。
public class ExampleSubProvider implements LootTableSubProvider {
// 供外层 Supplier 使用的工厂方法
public ExampleSubProvider() {}
@Override
public void generate(BiConsumer<ResourceLocation, LootTable.Builder> writer) {
// 调用 writer#accept 生成战利品表
}
}
然后可在 LootTableProvider#getTables 中为任意可用的 LootContextParamSet 添加该表:
// 在传入 LootTableProvider 构造函数的列表中
new LootTableProvider.SubProviderEntry(
ExampleSubProvider::new,
LootContextParamSets.EMPTY // 用于 empty 参数集的战利品表生成器
)
BlockLootSubProvider 和 EntityLootSubProvider 子类
对于 LootContextParamSets#BLOCK 和 #ENTITY,分别有特殊类型 BlockLootSubProvider 和 EntityLootSubProvider,提供创建战利品表及验证其存在的额外辅助方法。
BlockLootSubProvider 构造函数接收防爆物品列表,用于确定方块被炸毁时能否生成战利品表;还接收 FeatureFlagSet,用于确定方块是否启用,从而是否为其生成战利品表。
// 在 BlockLootSubProvider 子类中
public MyBlockLootSubProvider() {
super(Collections.emptySet(), FeatureFlags.REGISTRY.allFlags());
}
EntityLootSubProvider 构造函数接收 FeatureFlagSet,用于确定实体类型是否启用,从而是否为其生成战利品表。
public MyEntityLootSubProvider() {
super(FeatureFlags.REGISTRY.allFlags());
}
使用时,必须分别通过 BlockLootSubProvider#getKnownBlocks 和 EntityLootSubProvider#getKnownEntityTypes 提供所有注册对象。这些方法确保可迭代集合中的所有对象都有战利品表。
提示:如果使用
DeferredRegister注册模组对象,可通过DeferredRegister#getEntries为#getKnown*方法提供条目:
// 在 BlockLootSubProvider 子类中,假设存在 DeferredRegister BLOCK_REGISTRAR
@Override
protected Iterable<Block> getKnownBlocks() {
return BLOCK_REGISTRAR.getEntries() // 获取注册条目
.stream() // 流式处理包装对象
.flatMap(RegistryObject::stream) // 获取可用对象
::iterator; // 创建可迭代对象
}
实现 #generate 方法即可添加战利品表:
@Override
public void generate() {
// 在此添加战利品表
}
战利品表构建器
生成战利品表时,LootTableSubProvider 以 LootTable$Builder 接收表,随后设置 LootTableProvider$SubProviderEntry 指定的 LootContextParamSet 并通过 #build 构建。构建前可指定影响表运作方式的条目、条件和修饰器。
注意:战利品表功能十分广泛,本文无法完整涵盖,只简述各组件。各组件的具体子类型可以通过 IDE 查找,实现留给读者自行练习。
LootTable
战利品表是基础对象,可通过 LootTable#lootTable 转为所需的 LootTable$Builder。构建时可通过 #withPool 添加按指定顺序应用的战利品池列表,也可通过 #apply 添加函数以修改这些池产生的物品。
LootPool
战利品池表示一组操作,可通过 LootPool#lootPool 生成 LootPool$Builder。每个池可通过 #add 指定定义池内操作的条目,通过 #when 指定是否执行操作的条件,通过 #apply 指定修改条目产生物品的函数。可通过 #setRolls 指定池执行次数;还可通过 #setBonusRolls 指定受执行者幸运值影响的额外执行次数。
LootPoolEntryContainer
战利品条目定义被选中时的操作,通常生成物品。每个条目都有关联的已注册 LootPoolEntryType,以及继承 LootPoolEntryContainer$Builder 的构建器。可通过 #append 同时执行多个条目,通过 #then 顺序执行直到某个条目失败,也可通过 #otherwise 在失败时回退到另一个条目。
LootItemCondition
战利品条件定义执行某项操作必须满足的要求。每个条件都有关联的已注册 LootItemConditionType 和继承 LootItemCondition$Builder 的构建器。默认所有指定条件都必须返回 true 才执行;也可通过 #or 指定只需一个为真,或通过 #invert 反转条件结果。
LootItemFunction
战利品函数在结果送入输出前修改它。每个函数都有关联的已注册 LootItemFunctionType 和继承 LootItemFunction$Builder 的构建器。
NbtProvider
NBT 提供者是由 CopyNbtFunction 定义的特殊函数,用于指定从哪里获取标签信息。每个提供者都有关联的已注册 LootNbtProviderType。
NumberProvider
数字提供者决定战利品池执行次数。每个提供者都有关联的已注册 LootNumberProviderType。
ScoreboardNameProvider
记分板提供者是 ScoreboardValue 定义的特殊数字提供者,指定从哪个记分板名称读取执行次数。每个提供者都有关联的已注册 LootScoreProviderType。