数据包注册表对象提供器

数据包注册表对象生成

构造新的 DatapackBuiltinEntriesProvider 并提供包含待注册新对象的 RegistrySetBuilder,即可为模组生成数据包注册表对象。必须将提供者添加到 DataGenerator。

RegistrySetBuilder 为注册表配置 bootstrap;放置特征使用 lookup 和 getOrThrow 引用已注册的配置特征,再由 DatapackBuiltinEntriesProvider 生成条目数据。

原创说明图,依据 Forge 1.21.x 官方文档 绘制。

注意:DatapackBuiltinEntriesProvider 是 Forge 对 RegistriesDatapackGenerator 的扩展,能正确处理对已有数据包注册表对象的引用,而不会展开整个条目。因此本文使用它。

// 在模组事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
  event.getGenerator().addProvider(
    event.includeServer(), // 仅在生成服务端数据时运行
    output -> new DatapackBuiltinEntriesProvider(
      output,
      event.getLookupProvider(),
      new RegistrySetBuilder().add(/* ... */), // 包含待生成对象的 builder
      Set.of(MOD_ID) // 要生成其数据包注册表对象的模组 ID 集合
    )
  );
}

RegistrySetBuilder

RegistrySetBuilder 负责构建游戏中使用的所有数据包注册表对象。builder 可为注册表添加条目,然后向该注册表注册对象。

首先调用构造函数创建实例,然后调用 #add 处理特定注册表的注册。该方法接受注册表的 ResourceKey、包含注册对象所需 BootstapContext 的 RegistryBootstrap 消费者,以及可选的 Lifecycle 参数,表示注册表当前的生命周期状态。

new RegistrySetBuilder()
  .add(Registries.CONFIGURED_FEATURE, bootstrap -> {
    // 在此注册配置特征
  })
  .add(Registries.PLACED_FEATURE, bootstrap -> {
    // 在此注册放置特征
  });

注意:通过 Forge 创建的数据包注册表也可使用此 builder 生成对象,只需传入对应的 ResourceKey。

使用 BootstapContext 注册

使用 builder 提供的 BootstapContext#register 注册对象。参数为表示对象注册名的 ResourceKey、待注册对象,以及可选的 Lifecycle,用于表示注册对象当前的生命周期状态。

public static final ResourceKey<ConfiguredFeature<?, ?>> EXAMPLE_CONFIGURED_FEATURE = ResourceKey.create(
  Registries.CONFIGURED_FEATURE,
  ResourceLocation.fromNamespaceAndPath(MOD_ID, "example_configured_feature")
);

// 在某个常量位置或参数中
new RegistrySetBuilder()
  .add(Registries.CONFIGURED_FEATURE, bootstrap -> {
    bootstrap.register(
      EXAMPLE_CONFIGURED_FEATURE, // 配置特征的资源键
      new ConfiguredFeature<>(
        Feature.ORE, // 创建矿石特征
        new OreConfiguration(List.of(), 8) // 不执行操作;矿脉最多 8 个
      )
    );
  })
  .add(Registries.PLACED_FEATURE, bootstrap -> {
    // 在此注册放置特征
  });

查找数据包注册表对象

有时数据包注册表对象需要使用其他此类对象,或包含它们的标签。可通过 BootstapContext#lookup 查找另一个数据包注册表,获取 HolderGetter;再通过 #getOrThrow 传入对应键,取得对象的 Holder$Reference 或标签的 HolderSet$Named。

public static final ResourceKey<ConfiguredFeature<?, ?>> EXAMPLE_CONFIGURED_FEATURE = ResourceKey.create(
  Registries.CONFIGURED_FEATURE,
  ResourceLocation.fromNamespaceAndPath(MOD_ID, "example_configured_feature")
);
public static final ResourceKey<PlacedFeature> EXAMPLE_PLACED_FEATURE = ResourceKey.create(
  Registries.PLACED_FEATURE,
  ResourceLocation.fromNamespaceAndPath(MOD_ID, "example_placed_feature")
);

new RegistrySetBuilder()
  .add(Registries.CONFIGURED_FEATURE, bootstrap -> {
    bootstrap.register(EXAMPLE_CONFIGURED_FEATURE, new ConfiguredFeature(/* ... */));
  })
  .add(Registries.PLACED_FEATURE, bootstrap -> {
    HolderGetter<ConfiguredFeature<?, ?>> configured = bootstrap.lookup(Registries.CONFIGURED_FEATURE);
    bootstrap.register(
      EXAMPLE_PLACED_FEATURE,
      new PlacedFeature(
        configured.getOrThrow(EXAMPLE_CONFIGURED_FEATURE), // 获取配置特征
        List.of() // 不改变放置位置
      )
    );
  });

原文的放置特征示例中 bootstrap.register(...) 后缺少分号;译文已补上。

原文:Datapack Registry Object Generation。