Skip to main content
Version: 1.20.x

战利品表生成

可以通过构造新的LootTableProvider并提供LootTableProvider$SubProviderEntry来为模组生成战利品表。该提供者必须被添加DataGenerator中。

// 在模组事件总线上
@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,该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生成战利品表
}
}

The table can then be added to LootTableProvider#getTables for any available LootContextParamSet:

// 在将会传递给LootTableProvider构造函数的列表中
new LootTableProvider.SubProviderEntry(
ExampleSubProvider::new,
// 'empty'参数集的战利品表生成器
LootContextParamSets.EMPTY
)

BlockLootSubProviderEntityLootSubProvider子类

对于LootContextParamSets#BLOCK#ENTITY,有一些特殊类型(分别为BlockLootSubProviderEntityLootSubProvider),它们提供了额外的帮助方法来创建和验证是否存在战利品表。

BlockLootSubProvider的构造函数接受一个物品列表和一个FeatureFlagSet,前者是耐爆炸的,用于确定如果方块爆炸,是否可以生成战利品表,后者用于确定是否启用了该方块,以便为其生成战利品表。

// 在某个BlockLootSubProvider子类中
public MyBlockLootSubProvider() {
super(Collections.emptySet(), FeatureFlags.REGISTRY.allFlags());
}

EntityLootSubProvider的构造函数接受一个FeatureFlagSet,它确定是否启用了实体类型,以便为其生成战利品表。

// 在某个EntityLootSubProvider子类中
public MyEntityLootSubProvider() {
super(FeatureFlags.REGISTRY.allFlags());
}

要使用它们,所有注册的对象必须分别提供给BlockLootSubProvider#getKnownBlocksEntityLootSubProvider#getKnownEntityTypes。这些方法是为了确保Iterable中的所有对象都有一个战利品表。

!!! 提示 如果DeferredRegister用于注册模组的对象,则可以通过DeferredRegister#getEntries#getKnown*方法提供条目:

```java
// 在针对某个DeferredRegister BLOCK_REGISTRAR的某个BlockLootSubProvider子类中
@Override
protected Iterable<Block> getKnownBlocks() {
return BLOCK_REGISTRAR.getEntries() // 获取所有已注册的条目
.stream() // 流播所有已包装的对象
.flatMap(RegistryObject::stream) // 如果可行,获取该对象
::iterator; // 创建该Iterable
}
```

战利品表本身可以通过实现#generate方法来添加。

// 在某个BlockLootSubProvider子类中
@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才能执行操作。战利品条件也可以指定为只有一个必须返回true(通过#or)。此外,条件的结果输出可以反转(通过#invert)。

LootItemFunction

战利品函数在将执行结果传递给输出之前会对其进行修改。每个函数都有一个关联的已注册的LootItemFunctionType。它们也有自己的关联生成器,为LootItemFunction$Builder的子类型。

NbtProvider

NBT提供者是由CopyNbtFunction定义的一种特殊类型的函数。它们定义了从何处提取标记信息。每个提供者都有一个关联的已注册的LootNbtProviderType

NumberProvider

数字提供者决定战利品池执行的次数。每个提供者都有一个关联的已注册的LootNumberProviderType

ScoreboardNameProvider

记分牌提供者是由ScoreboardValue定义的一种特殊类型的数字提供者。他们定义了记分牌的名称,以获取要执行的掷数。每个提供者都有一个关联的已注册的LootScoreProviderType