From c97e85e32054c5efb2b2977f4446b91821adedf8 Mon Sep 17 00:00:00 2001 From: qiuye2024github Date: Wed, 29 Apr 2026 20:19:16 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 70 +++++---- README.md | 139 ++++++++++------ docs/advanced.md | 339 ++++++++++++++++++++++++++++++++++++++++ docs/architecture.md | 102 +++++++----- docs/builders.md | 331 +++++++++++++++++++++++++++++++++++++++ docs/entries.md | 262 +++++++++++++++++++++++++++++++ docs/getting-started.md | 101 ++++++++++++ docs/index.md | 45 ++++++ docs/providers.md | 272 ++++++++++++++++++++++++++++++++ 9 files changed, 1548 insertions(+), 113 deletions(-) create mode 100644 docs/advanced.md create mode 100644 docs/builders.md create mode 100644 docs/entries.md create mode 100644 docs/getting-started.md create mode 100644 docs/index.md create mode 100644 docs/providers.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 03c6997..ba9f119 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,34 +1,42 @@ -# Contributing +# 贡献指南 / Contributing -## Development Baseline +## 开发基线 / Development Baseline - Java: `25` -- Build tool: Gradle wrapper -- Recommended IDE: IntelliJ IDEA with the generated run configurations -- Line endings: `LF` via `.gitattributes` and `.editorconfig` - -## Local Workflow - -1. Sync the Gradle project with a Java 25 runtime. -2. Make changes inside the package layer that owns the behavior you are touching. -3. Validate with `./gradlew build` or `gradlew.bat build`. -4. Use the IDEA run configurations for interactive verification: - - `Client` - - `Server` - - `Data Generation` - - `Game Tests` - - `Game Tests (Client)` - -## Package Boundaries - -- Put fluent registration APIs in `com.modularmc.registrate.builders`. -- Put data generation wiring in `com.modularmc.registrate.providers`. -- Put generic runtime support code in `com.modularmc.registrate.util`. -- Keep typed registry wrappers in `com.modularmc.registrate.util.entry`. -- Avoid adding new public API surface to `util` when the concept belongs in a builder or provider. - -## Maintenance Notes - -- `RegistrateLib` is the library mod entrypoint for the fork and also holds shared metadata/constants. -- `src/test/java/com/modularmc/registrate/test/meta` contains maintenance helpers for generated bridge methods. -- When upstream Registrate changes, update implementation classes first and then re-verify package ownership against `docs/architecture.md`. +- 构建工具 / Build tool: Gradle wrapper +- 推荐 IDE / Recommended IDE: IntelliJ IDEA(使用生成的运行配置 / with the generated run configurations) +- 换行符 / Line endings: `LF`(通过 `.gitattributes` 和 `.editorconfig` / via `.gitattributes` and `.editorconfig`) + +## 本地工作流程 / Local Workflow + +1. 使用 Java 25 运行时同步 Gradle 项目 / Sync the Gradle project with a Java 25 runtime +2. 在你所接触的行为所属的包层内进行修改 / Make changes inside the package layer that owns the behavior you are touching +3. 使用 `./gradlew build` 或 `gradlew.bat build` 验证 / Validate with `./gradlew build` or `gradlew.bat build` +4. 使用 IDEA 运行配置进行交互式验证 / Use the IDEA run configurations for interactive verification: + - `Client` / 客户端 + - `Server` / 服务端 + - `Data Generation` / 数据生成 + - `Game Tests` / 游戏测试 + - `Game Tests (Client)` / 游戏测试(客户端) + +## 包边界 / Package Boundaries + +- 流式注册 API 放在 `com.modularmc.registrate.builders` + Put fluent registration APIs in `com.modularmc.registrate.builders` +- 数据生成连接放在 `com.modularmc.registrate.providers` + Put data generation wiring in `com.modularmc.registrate.providers` +- 通用运行时支持代码放在 `com.modularmc.registrate.util` + Put generic runtime support code in `com.modularmc.registrate.util` +- 类型化注册包装器保持在 `com.modularmc.registrate.util.entry` + Keep typed registry wrappers in `com.modularmc.registrate.util.entry` +- 当概念属于 builder 或 provider 时,避免向 `util` 添加新的公开 API 表面 + Avoid adding new public API surface to `util` when the concept belongs in a builder or provider + +## 维护说明 / Maintenance Notes + +- `RegistrateLib` 是本分支的库模组入口点,同时持有共享元数据/常量 + `RegistrateLib` is the library mod entrypoint for the fork and also holds shared metadata/constants +- `src/test/java/com/modularmc/registrate/test/meta` 包含用于生成的桥接方法的维护辅助工具 + `src/test/java/com/modularmc/registrate/test/meta` contains maintenance helpers for generated bridge methods +- 当上游 Registrate 变更时,先更新实现类,然后对照 `docs/architecture.md` 重新验证包所有权 + When upstream Registrate changes, update implementation classes first and then re-verify package ownership against `docs/architecture.md` diff --git a/README.md b/README.md index 733176c..c935c6a 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,90 @@ -# RegistrateLib [![Build Status](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fci.tterrag.com%2Fjob%2FRegistrate%2Fjob%2F1.21%2F)](https://ci.tterrag.com/job/Registrate/job/1.21) [![License](https://img.shields.io/github/license/ModularMCLib/RegistrateLib?cacheSeconds=36000)](https://www.tldrlegal.com/l/mpl-2.0) [![Maven Version](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.tterrag.com%2Fcom%2Ftterrag%2Fregistrate%2FRegistrate%2Fmaven-metadata.xml)](https://maven.tterrag.com/com/tterrag/registrate/Registrate) ![Minecraft Version](https://img.shields.io/badge/minecraft-26.1.1-blue) [![Discord](https://img.shields.io/discord/175740881389879296?label=discord&logo=discord&color=7289da)](https://discord.gg/gZqYcEj) +# RegistrateLib [![License](https://img.shields.io/github/license/ModularMCLib/RegistrateLib?cacheSeconds=36000)](https://www.tldrlegal.com/l/mpl-2.0) ![Minecraft Version](https://img.shields.io/badge/minecraft-26.1.1-blue) + + + +[![Build Status](#)]() +[![Maven Version](#)]() + +一个用于在你的模组中创建和注册对象的强大封装。 A powerful wrapper for creating and registering objects in your mod. -## Fork Status +--- + +## 分支状态 / Fork Status +本仓库是 `com.modularmc.registrate` 命名空间下的 Registrate 分支,为 ModularMCLib 生态维护。它追踪上游 Registrate 的设计,同时面向现代 NeoForge + Minecraft `26.1` 工具链,并保留可安全嵌入下游项目的包命名空间。 This repository is the `com.modularmc.registrate` fork maintained for the ModularMCLib ecosystem. It tracks the upstream Registrate design while targeting the modern NeoForge + Minecraft `26.1` toolchain and preserving a package namespace that can be safely embedded in downstream projects. -## Modern Development - -- Use `Java 25` for local builds and IDE sync. -- Prefer the bundled IDEA run configurations: `Client`, `Server`, `Data Generation`, `Game Tests`, and `Game Tests (Client)`. -- Keep fluent registration APIs in `builders`, data generation orchestration in `providers`, public reusable helpers in `util`, and implementation plumbing in `internal`. -- Treat [`docs/architecture.md`](docs/architecture.md) as the source of truth for package responsibilities and extension points. -- See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the day-to-day development workflow. - -## Code Classification - -- `com.modularmc.registrate`: public API roots, minimal library bootstrap, and the central registration coordinator. -- `com.modularmc.registrate.builders`: the fluent DSL used by downstream mods to register content. -- `com.modularmc.registrate.providers`: data generation orchestration and provider lifecycle management. -- `com.modularmc.registrate.providers.generators`: blockstate, model, and recipe generator adapters. -- `com.modularmc.registrate.providers.loot`: loot-table focused provider wrappers. -- `com.modularmc.registrate.util`: public shared helpers that remain part of the reusable library surface. -- `com.modularmc.registrate.util.entry`: strongly-typed registry handles returned by builders. -- `com.modularmc.registrate.util.nullness`: null-safe functional helpers and package defaults. -- `com.modularmc.registrate.internal`: non-API implementation details extracted from the core runtime. -- `com.modularmc.registrate.internal.event`: one-shot event wiring used by builders and registration lifecycle hooks. -- `com.modularmc.registrate.internal.lifecycle`: per-instance lifecycle bridges that keep NeoForge event hookups centralized without collapsing multiple mods into one shared runtime. -- `com.modularmc.registrate.internal.util`: dist-gated execution and internal logging helpers. -- `com.modularmc.registrate.test.mod`: the integration-style sample mod where non-library showcase behavior should live. -- `com.modularmc.registrate.test.gametests`: executable validation scenarios for runtime behavior. -- `com.modularmc.registrate.test.meta`: maintenance utilities that keep generated bridge methods aligned with upstream APIs. - -## Why Registrate? - -- Allows you to organize your mod content however you like, rather than having pieces of each object defined in scattered places -- Simple fluent API -- Open to extension, build and register custom objects and data -- Automatic data generation with sane defaults -- Usable as a standalone NeoForge library mod and as a declared dependency for downstream mods - -## How to Use +--- + +## 快速链接 / Quick Links + + +- Javadocs(待定 / TBD) +- [维基 / Wiki](https://github.com/ModularMCLib/RegistrateLib/wiki) +- [贡献指南 / Contributing](CONTRIBUTING.md) + +--- + +## 为什么使用 Registrate? / Why Registrate? + +- 你可以按照自己的方式组织模组内容,无需将每个对象的定义分散在各处 + Allows you to organize your mod content however you like, rather than having pieces of each object defined in scattered places +- 简洁的流式 API / Simple fluent API +- 可扩展,支持构建和注册自定义对象及数据 + Open to extension, build and register custom objects and data +- 自动数据生成,提供合理的默认值 + Automatic data generation with sane defaults +- 既可作为独立的 NeoForge 库模组使用,也可作为下游模组的声明依赖使用 + Usable as a standalone NeoForge library mod and as a declared dependency for downstream mods + +--- + +## 代码分类 / Code Classification +- `com.modularmc.registrate` — 公开 API 入口、最小化的库引导、注册协调中心 / public API roots, minimal library bootstrap, and the central registration coordinator +- `com.modularmc.registrate.builders` — 下游模组用于注册内容的流式 DSL / the fluent DSL used by downstream mods to register content +- `com.modularmc.registrate.providers` — 数据生成编排与提供者生命周期管理 / data generation orchestration and provider lifecycle management +- `com.modularmc.registrate.providers.generators` — 方块状态、模型和配方生成器适配器 / blockstate, model, and recipe generator adapters +- `com.modularmc.registrate.providers.loot` — 战利品表提供者封装 / loot-table focused provider wrappers +- `com.modularmc.registrate.util` — 公开的共享辅助工具 / public shared helpers that remain part of the reusable library surface +- `com.modularmc.registrate.util.entry` — 构建器返回的强类型注册句柄 / strongly-typed registry handles returned by builders +- `com.modularmc.registrate.util.nullness` — 空安全的函数式辅助与包级默认值 / null-safe functional helpers and package defaults +- `com.modularmc.registrate.internal` — 核心运行时的非 API 实现细节 / non-API implementation details extracted from the core runtime +- `com.modularmc.registrate.internal.event` — 用于构建器和注册生命周期钩子的一次性事件连接 / one-shot event wiring used by builders and registration lifecycle hooks +- `com.modularmc.registrate.internal.lifecycle` — 实例级生命周期桥接 / per-instance lifecycle bridges +- `com.modularmc.registrate.internal.util` — 分发限制执行与内部日志辅助 / dist-gated execution and internal logging helpers +- `com.modularmc.registrate.test.mod` — 集成测试示例模组 / the integration-style sample mod +- `com.modularmc.registrate.test.gametests` — 可执行的运行时验证场景 / executable validation scenarios for runtime behavior +- `com.modularmc.registrate.test.meta` — 维护工具,使生成的桥接方法与上游 API 保持一致 / maintenance utilities that keep generated bridge methods aligned with upstream APIs + +--- + +## 使用方法 / How to Use + +首先,创建一个 `Registrate` 对象,该对象将在整个项目中使用。 First, create a `Registrate` object which will be used across your entire project. ```java public static final Registrate REGISTRATE = Registrate.create(MOD_ID); ``` +不一定要使用常量字段,可以在注册设置完成后传递或丢弃。 Using a constant field is not necessary, it can be passed around and thrown away after registration is setup. +如果在 `@Mod` 类中声明为 `static`,必须延迟创建 `Registrate` 对象,避免在加载过程中过早创建。可以这样轻松实现: If declared static in your `@Mod` class, you must create the `Registrate` object lazily so it is not created too early during loading. This can be done easily like so: ```java public static final NonNullSupplier REGISTRATE = NonNullSupplier.lazy(() -> Registrate.create(MOD_ID)); ``` +接下来,开始添加对象。 Next, begin adding objects. -If you have a block class such as +如果你有一个方块类: +If you have a block class such as: ```java public class MyBlock extends Block { @@ -66,17 +92,19 @@ public class MyBlock extends Block { public MyBlock(Block.Properties properties) { super(properties); } - + ... } ``` -then register it like so, +可以这样注册: +then register it like so: ```java public static final RegistryEntry MY_BLOCK = REGISTRATE.block("my_block", MyBlock::new).register(); ``` +Registrate 会创建一个方块,并生成默认的简单方块状态、模型、战利品表和语言条目。所有这些方面都可以轻松配置为自定义数据。例如: Registrate will create a block, with a default simple blockstate, model, loot table, and lang entry. However, all of these facets can be configured easily to use whatever custom data you may want. Example: ```java @@ -89,14 +117,19 @@ public static final RegistryEntry MY_STAIRS = REGISTRATE.block("m .register(); ``` +这个自定义版本会创建 BlockItem(含默认模型和语言条目)、将方块添加到标签、配置楼梯属性方块状态,并添加自定义本地化。 This customized version will create a BlockItem (with its own default model and lang entry), add the block to a tag, configure the blockstate for stair properties, and add a custom localization. -To get an overview of the different APIs and methods, check out the [Javadocs](https://ci.tterrag.com/job/Registrate/job/1.21/javadoc/). For more advanced usage, read the [wiki](https://github.com/ModularMCLib/RegistrateLib/wiki) (WIP). + +有关不同 API 和方法的概述,请查阅 Javadocs(待定)。更高级的用法请阅读 [维基](https://github.com/ModularMCLib/RegistrateLib/wiki)(编写中)。 + +To get an overview of the different APIs and methods, check out the Javadocs (TBD). For more advanced usage, read the [wiki](https://github.com/ModularMCLib/RegistrateLib/wiki) (WIP). -## Project Setup +--- -For this `26.1` fork, the preferred integration model is to depend on RegistrateLib as a normal NeoForge library mod and declare it as a required dependency in your own metadata. Bundling remains possible for tightly controlled distributions, but standalone dependency loading is the default posture for this branch. +## 项目设置 / Project Setup +将库添加到 Gradle 依赖: Add the library to your Gradle dependencies: ```groovy @@ -105,6 +138,7 @@ dependencies { } ``` +然后在 `neoforge.mods.toml` 中将 `registratelib` 声明为必需依赖: Then declare `registratelib` as a required dependency in your `neoforge.mods.toml`: ```toml @@ -116,4 +150,21 @@ ordering="AFTER" side="BOTH" ``` -If you intentionally embed the library instead of loading it as a separate mod, keep your packaging and metadata strategy explicit so downstream debugging still has a clear ownership boundary. +--- + +## 开发指南 / Development + +- 使用 `Java 25` 进行本地构建和 IDE 同步 / Use `Java 25` for local builds and IDE sync +- 优先使用捆绑的 IDEA 运行配置:`Client`、`Server`、`Data Generation`、`Game Tests`、`Game Tests (Client)` + Prefer the bundled IDEA run configurations +- 流式注册 API 放在 `builders`,数据生成编排放在 `providers`,公开辅助工具放在 `util`,实现细节放在 `internal` + Keep fluent registration APIs in `builders`, data generation orchestration in `providers`, public reusable helpers in `util`, and implementation plumbing in `internal` +- 查看 [`docs/architecture.md`](docs/architecture.md) 了解包职责和扩展点 + See [`docs/architecture.md`](docs/architecture.md) for package responsibilities and extension points + +--- + +## 贡献 / Contributing + +请阅读 [`CONTRIBUTING.md`](CONTRIBUTING.md) 了解如何为此项目做出贡献。 +Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to contribute to this project. diff --git a/docs/advanced.md b/docs/advanced.md new file mode 100644 index 0000000..2aaeab5 --- /dev/null +++ b/docs/advanced.md @@ -0,0 +1,339 @@ +# 高级用法 / Advanced Usage + +--- + +## 自定义注册表 / Custom Registries + +RegistrateLib 支持创建内置注册表和数据包注册表。 +RegistrateLib supports creating both built-in and datapack registries. + +### 内置注册表 / Built-in Registry + +```java +// 创建内置注册表 / Create a built-in registry +public static final ResourceKey> CUSTOM_REGISTRY = + REGISTRATE.makeRegistry("custom", RegistryBuilder::new); + +// 使用该注册表注册对象 / Register objects with this registry +public static final RegistryEntry MY_CUSTOM = + REGISTRATE.object("testcustom") + .simple(CUSTOM_REGISTRY, MyCustomEntry::new); +``` + +### 数据包注册表 / Datapack Registry + +```java +// 创建数据包注册表(仅服务端同步)/ Datapack registry (server-side sync only) +public static final ResourceKey> MY_REGISTRY = + REGISTRATE.makeDatapackRegistry("my_registry", MyEntry.CODEC); + +// 创建数据包注册表(带网络同步)/ Datapack registry (with network sync) +public static final ResourceKey> MY_REGISTRY = + REGISTRATE.makeDatapackRegistry("my_registry", MyEntry.CODEC, MyEntry.NETWORK_CODEC); +``` + +--- + +## 生命周期钩子 / Lifecycle Hooks + +### onRegister —— 注册回调 + +在对象被注册到游戏注册表时触发。 +Fires when the object is registered into the game registry. + +```java +REGISTRATE.item("my_item", Item::new) + .onRegister(item -> { + // 注册时执行操作 / Do something on registration + LOGGER.info("Item registered: {}", item); + }) + .register(); +``` + +### onRegisterAfter —— 依赖注册回调 + +在指定注册表完成注册后触发。 +Fires after a specified registry finishes registration. + +```java +REGISTRATE.block("my_block", MyBlock::new) + .onRegisterAfter(Registries.BLOCK_ENTITY_TYPE, block -> { + // 方块实体注册后执行操作 / Do after block entities are registered + }) + .register(); +``` + +### 全局注册回调 / Global Registration Callbacks + +```java +// 特定条目的注册回调 / Per-entry registration callback +REGISTRATE.addRegisterCallback("my_block", Registries.BLOCK, block -> { + // ... +}); + +// 整个注册表的注册后回调 / Per-registry after-register callback +REGISTRATE.addRegisterCallback(Registries.BLOCK, () -> { + // 所有方块注册完成后执行 / All blocks registered +}); +``` + +--- + +## 数据生成器管理 / Data Generator Management + +### 设置/移除对象数据生成器 / Set/Remove Per-Object Data Generators + +```java +// 通过构建器设置数据生成器 / Via builder +builder.setData(ProviderType.RECIPE, (ctx, recipeProv) -> { ... }); +builder.removeData(ProviderType.RECIPE); + +// 通过 Registrate 实例 / Via Registrate instance +REGISTRATE.setDataGenerator(builder, ProviderType.RECIPE, consumer); +REGISTRATE.setDataGenerator("my_block", Registries.BLOCK, ProviderType.RECIPE, consumer); +REGISTRATE.removeDataGenerator(builder, ProviderType.RECIPE); +``` + +### 添加全局数据生成器 / Add Global Data Generators + +```java +REGISTRATE.addDataGenerator(ProviderType.LANG, langProvider -> { + langProvider.addBlock(MY_BLOCK); +}); +``` + +--- + +## 创造模式标签页 / Creative Mode Tabs + +### 设置默认创造模式标签页 / Set Default Creative Tab + +```java +// 方法 1:引用现有标签页 / Reference an existing tab +REGISTRATE.defaultCreativeTab(CreativeModeTabs.BUILDING_BLOCKS); + +// 方法 2:创建自定义标签页 / Create a custom tab +public static final RegistryEntry MY_TAB = + REGISTRATE.object("my_tab") + .defaultCreativeTab(tab -> tab.withLabelColor(0xFF00AA00)) + .register(); +``` + +### 将物品添加到标签页 / Add Items to Tabs + +```java +REGISTRATE.item("my_item", Item::new) + .tab(MY_TAB.getKey()) // 简单添加 / Simple add + .tab(MY_TAB.getKey(), (ctx, modifier) -> // 上下文感知添加 / Context-aware + modifier.accept(ctx)) + .removeTab(CreativeModeTabs.BUILDING_BLOCKS) // 从标签页移除 / Remove from tab + .register(); +``` + +### 修改现有标签页 / Modify Existing Tabs + +```java +REGISTRATE.modifyCreativeModeTab(CreativeModeTabs.INGREDIENTS, modifier -> { + modifier.accept(MY_ITEM); +}); +``` + +--- + +## 数据映射 / Data Maps + +```java +REGISTRATE.block("my_block", MyBlock::new) + .dataMap(DataMapTypes.FUEL, 300) // 设置燃料值 / Set fuel value + .register(); + +// 带上下文的工厂 / Context-aware factory +REGISTRATE.block("my_block", MyBlock::new) + .dataMap(DataMapTypes.FUEL, ctx -> { + // 根据上下文计算值 / Compute value from context + return ctx.getEntry().is(Blocks.DIAMOND) ? 3200 : 0; + }) + .register(); +``` + +--- + +## 转换器 / Transform + +可以使用 `.transform()` 方法将构建器传递给辅助函数。 +Use `.transform()` to pass the builder to helper functions. + +```java +// 定义可复用的变换函数 / Define reusable transform function +private static BlockBuilder applyDiamondDrop( + BlockBuilder builder) { + return builder.loot((prov, block) -> prov.dropOther(block, Items.DIAMOND)); +} + +// 在构建器中应用 / Apply in builder +REGISTRATE.block("my_block", MyBlock::new) + .transform(MyMod::applyDiamondDrop) + .register(); +``` + +--- + +## DataIngredient —— 数据驱动的配方便利工具 / Data-Driven Recipe Ingredient + +```java +// 从物品条目创建 / From item entries +DataIngredient.items(MY_ITEM); +DataIngredient.items(MY_BLOCK, MY_OTHER_ITEM); + +// 从标签创建 / From tags +DataIngredient.tag(ItemTags.PLANKS); + +// 结合 Ingredient / Combine with Ingredient +DataIngredient.ingredient(Ingredient.of(...), Items.DIAMOND); + +// 获取进度条件 / Get criterion for advancement unlock +DataIngredient.items(MY_ITEM).getCriterion(recipeProvider); +``` + +--- + +## CreativeModeTabModifier —— 标签页修改器 / Tab Modifier + +```java +// 在标签页修改回调中使用的输出接口 +// Output interface used in tab modification callbacks +public interface CreativeModeTab.Output { + void accept(ItemStack stack, CreativeModeTab.TabVisibility visibility); +} + +// CreativeModeTabModifier 额外方法 / CreativeModeTabModifier extras +modifier.getFlags(); // 获取功能标志 / Get feature flags +modifier.getParameters(); // 获取显示参数 / Get display parameters +modifier.hasPermissions(); // 是否有权限 / Has permissions +modifier.accept(itemLike); // 添加物品 / Add item (default visibility) +modifier.accept(itemLike, TabVisibility); // 添加物品(指定可见性)/ Add item with visibility +``` + +--- + +## 注册监听器管理 / Registration Listener Management + +`OneTimeEventReceiver` 提供了一次性事件监听器机制。 +Provides one-shot event listener mechanism. + +```java +// 添加一次性 mod 总线监听器 / Add one-shot mod bus listener +OneTimeEventReceiver.addModListener(registrate, RegisterEvent.class, event -> { + // 此监听器在第一次触发后自动取消注册 + // This listener auto-unregisters after first fire +}); +``` + +--- + +## 客户端扩展 / Client Extensions + +### 方块客户端扩展 / Block Client Extensions + +```java +REGISTRATE.block("my_block", MyBlock::new) + .clientExtension(() -> () -> new IClientBlockExtensions() { + // 自定义方块客户端行为 / Custom block client behavior + }) + .register(); +``` + +### 物品客户端扩展 / Item Client Extensions + +```java +REGISTRATE.item("my_item", Item::new) + .clientExtension(() -> () -> new IClientItemExtensions() { + // 自定义物品客户端行为 / Custom item client behavior + }) + .register(); +``` + +### 流体客户端扩展 / Fluid Client Extensions + +```java +REGISTRATE.fluid("my_fluid", still, flow, FluidType::new) + .clientExtension(() -> () -> new IClientFluidTypeExtensions() { + // 自定义流体客户端行为 / Custom fluid client behavior + }) + .register(); +``` + +--- + +## 颜色着色 / Color Tinting + +```java +// 方块着色 / Block tinting +REGISTRATE.block("my_block", MyBlock::new) + .color(() -> () -> List.of( + BlockTintSources.constant(0xFFFF0000) // 红色着色 / Red tint + )) + .register(); + +// 物品模型着色(通过 ItemBuilder)/ Item model tinting (via ItemBuilder) +REGISTRATE.item("my_item", Item::new) + .defaultModel(new ItemTintSource("layer0", Constant.create(0xFFFF0000))) + .register(); +``` + +--- + +## 延迟注册 / Deferred Registration + +对于在模组初始化后可能需要延迟解析的对象,可以使用 `NonNullSupplier.lazy()` 创建延迟初始化。 +For objects that need deferred resolution after mod initialisation, use `NonNullSupplier.lazy()`. + +```java +public static final NonNullSupplier REGISTRATE = + NonNullSupplier.lazy(() -> Registrate.create(MOD_ID)); +``` + +--- + +## 跳过错误 / Skipping Errors + +```java +// 在开发环境下跳过注册错误 / Skip registration errors in dev +REGISTRATE.skipErrors(true); +``` + +--- + +## 从现有对象获取条目 / Getting Entries from Existing Objects + +```java +// 从已注册的 Block 获取 BlockEntry +// Get BlockEntry from a registered block +BlockEntry entry = BlockEntry.cast( + registrate.get("existing_block", Registries.BLOCK)); + +// 检查对象是否已注册 +// Check if an object is registered +boolean registered = REGISTRATE.isRegistered(Registries.BLOCK); + +// 获取某注册表中的所有条目 +// Get all entries in a registry +Collection> allBlocks = + REGISTRATE.getAll(Registries.BLOCK); +``` + +--- + +## 注册多个名称相同的条目 / Registering Entries with the Same Name + +```java +// 使用相同的名称在不同注册表中注册不同对象 +// Register different objects with the same name in different registries +REGISTRATE.object("testitem") + .item(Item::new) + .register(); + +REGISTRATE.object("testitem") + .entity(TestEntity::new, MobCategory.CREATURE) + .register(); +``` diff --git a/docs/architecture.md b/docs/architecture.md index f81f407..a7db278 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,64 +1,90 @@ -# Architecture +# 架构 / Architecture -## Overview +## 概述 / Overview -`RegistrateLib` is a maintained fork of Registrate for the `com.modularmc.registrate` namespace. The project exposes a fluent registration API to downstream mods while keeping the implementation separated into registration, generation, runtime support, and test-maintenance layers. +RegistrateLib 是 Registrate 在 `com.modularmc.registrate` 命名空间下的维护分支,为 ModularMCLib 生态提供流式注册 API,将实现代码分离为注册、生成、运行时支持和测试维护等多个层次。 +RegistrateLib is a maintained fork of Registrate for the `com.modularmc.registrate` namespace. It exposes a fluent registration API while keeping the implementation separated into registration, generation, runtime support, and test-maintenance layers. -## Package Map +## 包映射 / Package Map - `com.modularmc.registrate` - - Public entrypoints. - - `AbstractRegistrate` is the orchestration core. - - `Registrate` is the default public implementation. - - `RegistrateLib` is the minimal NeoForge library entrypoint for this fork. + - 公开入口点 / Public entrypoints + - `AbstractRegistrate` 是编排核心 / is the orchestration core + - `Registrate` 是默认的公开实现 / is the default public implementation + - `RegistrateLib` 是 NeoForge 库模组入口点 / is the NeoForge library entrypoint + - `com.modularmc.registrate.builders` - - Public-facing fluent registration DSL. - - Owns object construction rules and builder chaining behavior. + - 面向用户的流式注册 DSL / Public-facing fluent registration DSL + - 拥有对象构造规则和链式调用行为 / Owns object construction rules and builder chaining behavior + - `com.modularmc.registrate.providers` - - Data generation lifecycle, provider registration, and provider dispatch. + - 数据生成生命周期、提供者注册和分发 / Data generation lifecycle, provider registration, and provider dispatch + - `com.modularmc.registrate.providers.generators` - - Specialized adapters for recipes, models, and blockstates. + - 配方、模型和方块状态的专用适配器 / Specialized adapters for recipes, models, and blockstates + - `com.modularmc.registrate.providers.loot` - - Loot-specific provider wrappers and compatibility helpers. + - 战利品表提供者封装与兼容辅助 / Loot-specific provider wrappers and compatibility helpers + - `com.modularmc.registrate.util` - - Shared downstream-facing runtime and data helpers that remain part of the reusable library surface. + - 面向下游的共享运行时和数据辅助工具 / Shared downstream-facing runtime and data helpers + - `com.modularmc.registrate.util.entry` - - Strongly-typed handles returned from registrations. + - 注册返回的强类型句柄 / Strongly-typed handles returned from registrations + - `com.modularmc.registrate.util.nullness` - - Functional interfaces and package-level nullness conventions. + - 函数式接口与包级空值约定 / Functional interfaces and package-level nullness conventions + - `com.modularmc.registrate.internal` - - Non-public state trackers and implementation support types extracted from the central core. + - 从核心提取的非公开状态跟踪器和实现辅助类型 / Non-public state trackers and implementation support types + - `com.modularmc.registrate.internal.event` - - One-shot mod event wiring used to bridge builder callbacks onto the NeoForge mod bus. + - 用于将构建器回调桥接到 NeoForge mod 总线的一次性事件连接 / One-shot mod event wiring used to bridge builder callbacks onto the NeoForge mod bus + - `com.modularmc.registrate.internal.lifecycle` - - Per-instance lifecycle bridges that centralize `RegisterEvent`, creative-tab, and datagen bus wiring without introducing a shared global core. + - 实例级生命周期桥接,集中处理 `RegisterEvent`、创造模式标签页和数据生成总线连接 / Per-instance lifecycle bridges that centralize event wiring + - `com.modularmc.registrate.internal.util` - - Dist-gated execution and internal debug logging helpers. + - 分发限制执行与内部调试日志辅助 / Dist-gated execution and internal debug logging helpers + - `com.modularmc.registrate.test.mod` - - Sample mod used as an integration harness. + - 用作集成测试的示例模组 / Sample mod used as an integration harness + - `com.modularmc.registrate.test.gametests` - - Executable runtime checks. + - 可执行的运行时检查 / Executable runtime checks + - `com.modularmc.registrate.test.meta` - - Maintenance tooling for generated bridge methods and protected API snapshots. + - 用于生成的桥接方法和受保护 API 快照的维护工具 / Maintenance tooling for generated bridge methods and protected API snapshots -## Public API Boundary +## 公开 API 边界 / Public API Boundary +将根包、`builders` 和 `util.entry` 视为面向下游的主要 API 表面。提供者和工具包也是可复用的,但它们主要用于支持 API,而非主要扩展点。 Treat the root package plus `builders` and `util.entry` as the main downstream-facing API surface. Provider and utility packages are reusable, but most of them exist to support the API rather than to be primary extension points. -## Placement Guide +## 放置指南 / Placement Guide -- New registration DSL behavior belongs in `builders`. -- New datagen orchestration belongs in `providers`. -- Generator-specific helpers belong in `providers.generators` or `providers.loot`. -- Cross-cutting runtime support belongs in `util` only when it is not builder- or provider-specific. -- Event-bus plumbing and other implementation-only helpers belong under `internal`. -- Instance-scoped NeoForge lifecycle orchestration belongs in `internal.lifecycle`. -- Test-only scaffolding belongs under `src/test/java` even if it mirrors production APIs. -- Sample visuals, showcase content, and anything that is not intrinsic to the reusable registration library should also stay under `src/test`. +- 新的注册 DSL 行为放在 `builders` + New registration DSL behavior belongs in `builders` +- 新的数据生成编排放在 `providers` + New datagen orchestration belongs in `providers` +- 生成器专属辅助放在 `providers.generators` 或 `providers.loot` + Generator-specific helpers belong in `providers.generators` or `providers.loot` +- 跨切面的运行时支持,仅当不特定于 builder 或 provider 时才放在 `util` + Cross-cutting runtime support belongs in `util` only when it is not builder- or provider-specific +- 事件总线连接和其他仅实现辅助放在 `internal` + Event-bus plumbing and other implementation-only helpers belong under `internal` +- 实例级 NeoForge 生命周期编排放在 `internal.lifecycle` + Instance-scoped NeoForge lifecycle orchestration belongs in `internal.lifecycle` +- 仅测试用的框架放在 `src/test/java` + Test-only scaffolding belongs under `src/test/java` -## Modernization Principles +## 现代化原则 / Modernization Principles -- Prefer explicit package ownership over convenience placement. -- Keep public entrypoints small and push complexity into focused layers. -- Document extension points where downstream mods are expected to integrate. -- Favor 26.1-native structure over preserving legacy compatibility on this dev branch. +- 偏好明确的包所有权而非便利放置 + Prefer explicit package ownership over convenience placement +- 保持公开入口点小巧,将复杂性推入专注的层次 + Keep public entrypoints small and push complexity into focused layers +- 对下游模组预期集成的扩展点进行文档化 + Document extension points where downstream mods are expected to integrate +- 在此开发分支上,优先采用 26.1 原生结构而非保持遗留兼容性 + Favor 26.1-native structure over preserving legacy compatibility on this dev branch diff --git a/docs/builders.md b/docs/builders.md new file mode 100644 index 0000000..1f350fa --- /dev/null +++ b/docs/builders.md @@ -0,0 +1,331 @@ +# 构建器 API / Builder API + +RegistrateLib 使用**流式构建器模式**(Fluent Builder Pattern)来声明和管理对象注册。每个构建器都提供链式方法调用来配置对象的不同方面,最后通过 `register()` 完成注册。 + +RegistrateLib uses the **Fluent Builder Pattern** to declare and manage object registration. Each builder provides chainable methods to configure different aspects of the object, finalised with `register()`. + +--- + +## 目录 / Table of Contents + +1. [AbstractBuilder —— 所有构建器的基类](#abstractbuilder) +2. [BlockBuilder —— 方块构建器](#blockbuilder) +3. [ItemBuilder —— 物品构建器](#itembuilder) +4. [BlockEntityBuilder —— 方块实体构建器](#blockentitybuilder) +5. [EntityBuilder —— 实体构建器](#entitybuilder) +6. [FluidBuilder —— 流体构建器](#fluidbuilder) +7. [MenuBuilder —— 菜单构建器](#menubuilder) + +--- + +## AbstractBuilder + +所有构建器的抽象基类,提供通用的构建器方法。 +Abstract base class for all builders, providing common builder methods. + +```java +public abstract class AbstractBuilder> +``` + +### 通用方法 / Common Methods + +| 方法 / Method | 描述 / Description | +|--------------------------------------------|-----------------------------------------------------------------------------------------------| +| `register()` | 完成注册,返回对应的 `RegistryEntry` / Finalise registration, returns the corresponding `RegistryEntry` | +| `tag(ProviderType, TagKey...)` | 为对象添加标签(通用版)/ Add tags to the object (generic) | +| `removeTag(ProviderType, TagKey...)` | 移除对象的标签 / Remove tags from the object | +| `lang(NonNullFunction, String)` | 设置自定义语言键 / Set a custom lang key | +| `asOptional()` | 将此构建器标记为可选的 / Mark this builder as optional | +| `getResourceKey()` | 获取此构建器创建的资源的 `ResourceKey` / Get the `ResourceKey` for the resource | + +### Builder 接口方法 / Builder Interface Methods + +以下方法在 `Builder` 接口中定义,对所有构建器可用: +These methods are defined in the `Builder` interface and available on all builders: + +| 方法 / Method | 描述 / Description | +|-------------------------------------------------|------------------------------------------------------------------------| +| `setData(GeneratorType, NonNullBiConsumer)` | 为此对象设置数据生成器 / Set a data generator for this object | +| `removeData(GeneratorType)` | 移除数据生成器 / Remove a data generator | +| `addMiscData(GeneratorType, NonNullConsumer)` | 添加全局数据生成器 / Add a global data generator | +| `dataMap(DataMapType, ...)` | 为此对象添加数据映射 / Add a data map value | +| `onRegister(NonNullConsumer)` | 注册完成时的回调 / Callback when registration completes | +| `onRegisterAfter(ResourceKey, NonNullConsumer)` | 在指定注册表注册完成后的回调 / Callback after another registry finishes registration | +| `transform(NonNullFunction)` | 对构建器应用变换函数 / Apply a transform function to the builder | +| `build()` | 返回父构建器(用于嵌套构建器链)/ Return to parent builder | + +--- + +## BlockBuilder + +用于注册方块。 +Used for registering blocks. + +```java +public class BlockBuilder + extends AbstractBuilder> +``` + +### 创建 / Creation + +```java +// 由 Registrate 的 block() 方法创建 / Created via Registrate's block() method +registrate.block("my_block", MyBlock::new) +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------| +| `properties(NonNullUnaryOperator)` | 修改方块属性 / Modify block properties | +| `initialProperties(NonNullSupplier)` | 从现有方块复制初始属性 / Copy initial properties from an existing block | +| `simpleItem()` | 自动创建一个默认的 BlockItem / Automatically create a default BlockItem | +| `item()` | 返回 `ItemBuilder>`,用于自定义 BlockItem / Return ItemBuilder for custom BlockItem | +| `item(NonNullBiFunction)` | 使用自定义工厂创建 BlockItem / Create BlockItem with a custom factory | +| `simpleBlockEntity(BlockEntityFactory)` | 快速创建没有额外配置的方块实体 / Quickly create a block entity without extra configuration | +| `blockEntity(BlockEntityFactory)` | 返回 `BlockEntityBuilder` 用于完全配置方块实体 / Return BlockEntityBuilder for full BE configuration | +| `color(NonNullSupplier>>)` | 设置方块着色器 / Set block tint sources | +| `defaultBlockstate()` | 使用默认方块状态生成 / Use default blockstate generation | +| `blockstate(NonNullSupplier)` | 自定义方块状态生成 / Custom blockstate generation | +| `defaultLang()` | 自动生成语言条目 / Auto-generate lang entry | +| `lang(String)` | 自定义语言名称 / Custom lang name | +| `defaultLoot()` | 使用默认战利品表生成 / Use default loot table generation | +| `loot(NonNullBiConsumer)` | 自定义战利品表生成 / Custom loot table generation | +| `recipe(NonNullBiConsumer)` | 添加配方生成 / Add recipe generation | +| `clientExtension(NonNullSupplier>)` | 添加客户端扩展 / Add client block extensions | +| `tag(TagKey...)` | 添加方块标签 / Add block tags | +| `register()` | 返回 `BlockEntry` / Returns `BlockEntry` | + +### 示例 / Example + +```java +public static final BlockEntry MY_STAIRS = REGISTRATE + .block("my_stairs", MyStairsBlock::new) + .defaultItem() // 或 .item() 进行自定义 / or .item() for custom + .tag(BlockTags.STAIRS) + .blockstate(ctx -> ctx.getProvider() + .stairsBlock(ctx.getEntry(), ctx.getProvider().modLoc(ctx.getName()))) + .lang("Special Stairs") + .register(); +``` + +--- + +## ItemBuilder + +用于注册物品。 +Used for registering items. + +```java +public class ItemBuilder + extends AbstractBuilder> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|---------------------------------------------------------------------|--------------------------------------------| +| `properties(NonNullUnaryOperator)` | 修改物品属性 / Modify item properties | +| `initialProperties(NonNullSupplier)` | 使用初始属性 / Use initial properties | +| `tab(ResourceKey, ...)` | 添加到创造模式标签页 / Add to creative mode tab | +| `removeTab(ResourceKey)` | 从标签页移除 / Remove from tab | +| `defaultModel()` | 使用默认物品模型 / Use default item model | +| `model(NonNullSupplier)` | 自定义物品模型 / Custom item model | +| `defaultLang()` | 自动生成语言条目 / Auto-generate lang entry | +| `lang(String)` | 自定义语言名称 / Custom lang name | +| `recipe(NonNullBiConsumer)` | 添加配方生成 / Add recipe | +| `burnTime(int)` | 设置燃料燃烧时间(tick)/ Set fuel burn time (ticks) | +| `compostable(float)` | 设置堆肥机概率 / Set composter chance | +| `clientExtension(NonNullSupplier>)` | 添加客户端扩展 / Add client item extensions | +| `tag(TagKey...)` | 添加物品标签 / Add item tags | +| `register()` | 返回 `ItemEntry` / Returns `ItemEntry` | + +### 示例 / Example + +```java +public static final ItemEntry MY_ITEM = REGISTRATE + .item("my_item", Item::new) + .properties(p -> p.food(new FoodProperties.Builder() + .nutrition(4).saturationModifier(0.5f).build())) + .tag(ItemTags.FOOD) + .tab(MyMod.CREATIVE_TAB) + .register(); +``` + +--- + +## BlockEntityBuilder + +用于注册方块实体。 +Used for registering block entities. + +```java +public class BlockEntityBuilder + extends AbstractBuilder, BlockEntityType, P, BlockEntityBuilder> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|-----------------------------------------------------------|----------------------------------------------------------| +| `validBlock(NonNullSupplier)` | 为此方块实体关联一个有效方块 / Associate a valid block with this BE | +| `validBlocks(NonNullSupplier...)` | 关联多个有效方块 / Associate multiple valid blocks | +| `renderer(NonNullSupplier)` | 设置方块实体渲染器 / Set block entity renderer | +| `registerCapability(Consumer)` | 注册能力(Capability)/ Register capabilities | +| `register()` | 返回 `BlockEntityEntry` / Returns `BlockEntityEntry` | + +### 示例 / Example + +```java +public static final BlockEntityEntry MY_BE = REGISTRATE + .blockEntity("my_be", MyBlockEntity::new) + .validBlock(() -> MyMod.MY_BLOCK) + .renderer(() -> MyBERenderer::new) + .register(); +``` + +--- + +## EntityBuilder + +用于注册实体。 +Used for registering entities. + +```java +public class EntityBuilder + extends AbstractBuilder, EntityType, P, EntityBuilder> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|----------------------------------------------------------------------------------|------------------------------------------------| +| `properties(NonNullConsumer>)` | 修改实体类型属性 / Modify entity type properties | +| `renderer(NonNullSupplier)` | 设置实体渲染器 / Set entity renderer | +| `attributes(Supplier)` | 设置实体属性 / Set entity attributes | +| `spawnPlacement(SpawnPlacementType, Heightmap.Types, SpawnPredicate, Operation)` | 设置生成放置规则 / Set spawn placement rules | +| `spawnEgg()` | 自动生成刷怪蛋 / Auto-generate spawn egg | +| `spawnEgg(NonNullConsumer)` | 自定义刷怪蛋 / Custom spawn egg | +| `defaultLang()` | 自动生成语言条目 / Auto-generate lang entry | +| `lang(String)` | 自定义语言名称 / Custom lang name | +| `loot(NonNullBiConsumer)` | 自定义战利品表 / Custom loot table | +| `tag(TagKey>...)` | 添加实体标签 / Add entity type tags | +| `register()` | 返回 `EntityEntry` / Returns `EntityEntry` | + +### 示例 / Example + +```java +public static final EntityEntry MY_ENTITY = REGISTRATE + .entity("my_entity", MyEntity::new, MobCategory.CREATURE) + .attributes(MyEntity::createAttributes) + .renderer(() -> MyEntityRenderer::new) + .spawnEgg() + .spawnPlacement(SpawnPlacementTypes.ON_GROUND, + Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, + Animal::checkAnimalSpawnRules, + RegisterSpawnPlacementsEvent.Operation.OR) + .loot((prov, type) -> prov.add(type, LootTable.lootTable() + .withPool(LootPool.lootPool() + .add(LootItem.lootTableItem(Items.DIAMOND))))) + .register(); +``` + +--- + +## FluidBuilder + +用于注册流体。 +Used for registering fluids. + +```java +public class FluidBuilder + extends AbstractBuilder> +``` + +### 创建 / Creation + +```java +// 基本创建(默认 FluidType)/ Basic creation (default FluidType) +registrate.fluid("my_fluid", + Identifier.of("minecraft:block/water_still"), + Identifier.of("minecraft:block/water_flow"), + FluidType::new) +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|-----------------------------------------------------------------|----------------------------------------------------------------| +| `properties(NonNullConsumer)` | 修改流体类型属性 / Modify fluid type properties | +| `fluidProperties(NonNullConsumer)` | 修改流体属性 / Modify fluid properties | +| `defaultLang()` | 自动生成语言条目 / Auto-generate lang entry | +| `lang(String)` | 自定义语言名称 / Custom lang name | +| `defaultSource()` | 使用默认流体源 / Use default fluid source | +| `source(NonNullFunction)` | 自定义流体源 / Custom fluid source | +| `defaultBlock()` | 自动生成流体方块 / Auto-generate fluid block | +| `block()` | 返回 `BlockBuilder` 配置流体方块 / Return BlockBuilder for fluid block | +| `block(NonNullBiFunction)` | 使用自定义工厂创建流体方块 / Custom fluid block factory | +| `noBlock()` | 不生成流体方块 / Skip fluid block generation | +| `defaultBucket()` | 自动生成流体桶 / Auto-generate fluid bucket | +| `bucket()` | 返回 `ItemBuilder` 配置流体桶 / Return ItemBuilder for bucket | +| `bucket(NonNullBiFunction)` | 自定义桶 / Custom bucket | +| `noBucket()` | 不生成桶 / Skip bucket generation | +| `model(Identifier, Identifier)` | 设置静态和流动纹理 / Set still and flowing textures | +| `model(NonNullSupplier)` | 自定义模型 / Custom model | +| `clientExtension(NonNullSupplier)` | 添加客户端流体类型扩展 / Add client fluid type extensions | +| `tag(TagKey...)` | 添加流体标签 / Add fluid tags | +| `removeTag(TagKey...)` | 移除流体标签 / Remove fluid tags | +| `register()` | 返回 `FluidEntry` / Returns `FluidEntry` | + +### 示例 / Example + +```java +public static final FluidEntry MY_FLUID = REGISTRATE + .fluid("my_fluid", + Identifier.of("minecraft:block/water_still"), + Identifier.of("minecraft:block/water_flow"), + FluidType::new) + .properties(p -> p.lightLevel(15).canConvertToSource(true)) + .register(); +``` + +--- + +## MenuBuilder + +用于注册菜单(容器界面)。 +Used for registering menus (container screens). + +```java +public class MenuBuilder, P> + extends AbstractBuilder, MenuType, P, MenuBuilder> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|--------------|--------------------------------------------| +| `register()` | 返回 `MenuEntry` / Returns `MenuEntry` | + +### 工厂接口 / Factory Interfaces + +```java +// 标准菜单工厂 / Standard menu factory +MenuFactory // (type, windowId, inv) -> T + +// Forge 扩展菜单工厂(支持缓冲区)/ Forge extended menu factory (with buffer) +ForgeMenuFactory // (type, windowId, inv, buffer) -> T + +// 屏幕工厂 / Screen factory +ScreenFactory // (menu, inv, displayName) -> S +``` + +### 示例 / Example + +```java +public static final MenuEntry MY_MENU = REGISTRATE + .menu("my_menu", + (type, windowId, inv) -> new ChestMenu(type, windowId, inv, new SimpleContainer(9), 9), + () -> ContainerScreen::new) + .register(); +``` diff --git a/docs/entries.md b/docs/entries.md new file mode 100644 index 0000000..9fbb5c8 --- /dev/null +++ b/docs/entries.md @@ -0,0 +1,262 @@ +# 注册条目 / Registry Entries + +当构建器调用 `register()` 后,会返回一个强类型的 `RegistryEntry` 句柄。这些条目提供了类型安全的方式来引用和使用已注册的对象。 + +When a builder's `register()` is called, it returns a strongly-typed `RegistryEntry` handle. These entries provide a type-safe way to reference and use registered objects. + +--- + +## RegistryEntry —— 基础条目 / Base Entry + +所有注册条目的基类。 +Base class for all registry entries. + +```java +public class RegistryEntry extends DeferredHolder + implements NonNullSupplier +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|---------------------------|------------------------------------------------------------------| +| `get()` | 获取注册对象(继承自 `NonNullSupplier`)/ Get the registered object | +| `getSibling(ResourceKey)` | 按注册表键获取兄弟条目(如方块获取其 BlockItem)/ Get sibling entry by registry key | +| `getSibling(Registry)` | 按注册表实例获取兄弟条目 / Get sibling entry by registry instance | +| `getSiblingOptional(...)` | 获取可选的兄弟条目 / Get optional sibling entry | +| `filter(Predicate)` | 按谓词过滤条目 / Filter entry by predicate | +| `is(Object)` | 检查条目是否等于给定对象 / Check if entry equals given object | + +### 兄弟条目示例 / Sibling Example + +```java +// 从方块获取其 BlockItem 条目 +// Get BlockItem entry from a block +ItemEntry blockItem = ItemEntry.cast( + MY_BLOCK.getSibling(Registries.ITEM)); + +// 从方块获取其方块实体条目 +// Get BE entry from a block +BlockEntityEntry be = BlockEntityEntry.cast( + MY_BLOCK.getSibling(Registries.BLOCK_ENTITY_TYPE)); +``` + +--- + +## ItemProviderEntry —— 可提供物品的条目 / Item-able Entry + +`BlockEntry` 和 `ItemEntry` 的基类,实现了 `ItemLike`。 +Base class for `BlockEntry` and `ItemEntry`, implements `ItemLike`. + +```java +public class ItemProviderEntry + extends RegistryEntry implements ItemLike +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|---------------------|-------------------------------------------------------------------------| +| `asStack()` | 创建包含此物品的 `ItemStack`(数量 1)/ Create an ItemStack (count 1) | +| `asStack(int)` | 创建指定数量的 `ItemStack` / Create an ItemStack with specified count | +| `asStackTemplate()` | 创建 `ItemStackTemplate`(用于配方)/ Create an ItemStackTemplate (for recipes) | +| `isIn(ItemStack)` | 检查物品栈是否包含此物品 / Check if a stack contains this item | +| `is(Item)` | 检查是否特定物品 / Check if specific item | +| `asItem()` | 获取 `Item` 对象 / Get the Item object | + +--- + +## BlockEntry —— 方块条目 / Block Entry + +```java +public class BlockEntry extends ItemProviderEntry +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|-----------------------|------------------------------------------------------| +| `getDefaultState()` | 获取默认方块状态 / Get default block state | +| `has(BlockState)` | 检查方块状态是否属于此方块 / Check if state belongs to this block | +| `cast(RegistryEntry)` | 静态转换方法 / Static cast method | + +### 示例 / Example + +```java +public static final BlockEntry MY_BLOCK = REGISTRATE + .block("my_block", MyBlock::new).simpleItem().register(); + +// 使用 / Usage +BlockState state = MY_BLOCK.getDefaultState(); +ItemStack stack = MY_BLOCK.asStack(); +boolean isMyBlock = MY_BLOCK.has(someState); +``` + +--- + +## ItemEntry —— 物品条目 / Item Entry + +```java +public class ItemEntry extends ItemProviderEntry +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|-----------------------|-----------------------------| +| `cast(RegistryEntry)` | 静态转换方法 / Static cast method | + +### 示例 / Example + +```java +public static final ItemEntry MY_ITEM = REGISTRATE + .item("my_item", Item::new).register(); + +// 使用 / Usage +ItemStack stack = MY_ITEM.asStack(64); +boolean isFood = MY_ITEM.is(Items.APPLE); +``` + +--- + +## BlockEntityEntry —— 方块实体条目 / Block Entity Entry + +```java +public class BlockEntityEntry + extends RegistryEntry, BlockEntityType> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|--------------------------------------|-----------------------------------------------------| +| `create(BlockPos, BlockState)` | 在指定位置创建方块实体实例 / Create a BE instance at a position | +| `is(BlockEntity)` | 检查方块实体是否属于此类型 / Check if BE is of this type | +| `get(BlockGetter, BlockPos)` | 从世界中获取可选的方块实体实例 / Get optional BE from world | +| `getNullable(BlockGetter, BlockPos)` | 从世界中获取可能为 null 的方块实体实例 / Get nullable BE from world | +| `cast(RegistryEntry)` | 静态转换方法 / Static cast method | + +### 示例 / Example + +```java +// 获取世界中的方块实体 +// Get BE in world +Optional be = MY_BE.get(level, pos); + +// 创建新实例 +// Create new instance +MyBE newBe = MY_BE.create(pos, state); +``` + +--- + +## EntityEntry —— 实体条目 / Entity Entry + +```java +public class EntityEntry + extends RegistryEntry, EntityType> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|------------------------------------|-----------------------------------------------| +| `create(Level, EntitySpawnReason)` | 创建实体实例 / Create an entity instance | +| `is(Entity)` | 检查实体是否属于此类型 / Check if entity is of this type | +| `cast(RegistryEntry)` | 静态转换方法 / Static cast method | + +### 示例 / Example + +```java +// 生成实体 +// Spawn entity +MyEntity entity = MY_ENTITY.create(level, EntitySpawnReason.SPAWN_EGG); +entity.setPos(x, y, z); +level.addFreshEntity(entity); +``` + +--- + +## FluidEntry —— 流体条目 / Fluid Entry + +```java +public class FluidEntry + extends RegistryEntry +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|---------------|----------------------------------------------------------------------------| +| `is(Object)` | 使用 `Fluid.isSame()` 检查流体是否相同 / Check fluid equality using `Fluid.isSame()` | +| `getSource()` | 获取此流体的源变体 / Get the source variant of this fluid | +| `getType()` | 获取 `FluidType` / Get the `FluidType` | +| `getBlock()` | 获取流体方块(如存在) / Get the fluid block (if present) | +| `getBucket()` | 获取流体桶物品(如存在) / Get the bucket item (if present) | + +### 示例 / Example + +```java +public static final FluidEntry MY_FLUID = REGISTRATE + .fluid("my_fluid", still, flow, FluidType::new).register(); + +// 使用 / Usage +Fluid source = MY_FLUID.getSource(); +Optional block = MY_FLUID.getBlock(); +Optional bucket = MY_FLUID.getBucket(); +boolean isSame = MY_FLUID.is(otherFluid); +``` + +--- + +## MenuEntry —— 菜单条目 / Menu Entry + +```java +public class MenuEntry + extends RegistryEntry, MenuType> +``` + +### 方法 / Methods + +| 方法 / Method | 描述 / Description | +|--------------------------------------------------------------------|------------------------------------------------------| +| `create(int, Inventory)` | 创建菜单实例 / Create a menu instance | +| `asProvider()` | 获取 `MenuConstructor` / Get a `MenuConstructor` | +| `open(ServerPlayer, Component)` | 为玩家打开菜单 / Open the menu for a player | +| `open(ServerPlayer, Component, Consumer)` | 打开菜单并传递额外数据 / Open menu with extra data | +| `open(ServerPlayer, Component, MenuConstructor)` | 使用自定义提供者打开菜单 / Open with custom provider | +| `open(ServerPlayer, Component, MenuConstructor, Consumer)` | 使用自定义提供者和数据打开菜单 / Open with custom provider and data | + +### 示例 / Example + +```java +// 在服务器端为玩家打开菜单 +// Open menu for a player on the server side +MY_MENU.open(player, Component.literal("My Menu")); + +// 带额外数据 +// With extra data +MY_MENU.open(player, Component.literal("My Menu"), buf -> { + buf.writeUtf("extra data"); +}); +``` + +--- + +## LazyRegistryEntry —— 延迟解析条目 / Lazy Entry + +用于需要延迟解析注册条目的场景,避免在类加载阶段提前触发注册。 +Used when registry entry resolution needs to be deferred to avoid triggering registration early during class loading. + +```java +public class LazyRegistryEntry implements NonNullSupplier +``` + +### 构造 / Construction + +```java +LazyRegistryEntry<>(NonNullSupplier> supplier) +``` + +解析一次后缓存结果,并释放 supplier 引用以允许 GC。 +Resolves once, caches the result, and releases the supplier reference for GC. diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..13405d3 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,101 @@ +# 快速入门 / Getting Started + +## 安装 / Installation + +### 1. 添加依赖 / Add Dependency + +在 `build.gradle` 中添加: +Add to your `build.gradle`: + +```groovy +dependencies { + implementation "com.modularmc.registrate:registratelib:${registratelib_version}" +} +``` + +### 2. 声明依赖 / Declare Dependency + +在 `neoforge.mods.toml` 中添加: +Add to your `neoforge.mods.toml`: + +```toml +[[dependencies.yourmodid]] +modId="registratelib" +type="required" +versionRange="[2.0.0,)" +ordering="AFTER" +side="BOTH" +``` + +## 创建 Registrate 实例 / Creating a Registrate Instance + +在你的主模组类中创建一个 `Registrate` 对象: +Create a `Registrate` object in your main mod class: + +```java +@Mod(MyMod.MOD_ID) +public class MyMod { + public static final String MOD_ID = "mymod"; + + // 简单方式(注意:需确保不在构造之前访问) + // Simple approach (ensure it's not accessed before construction) + public static final Registrate REGISTRATE = Registrate.create(MOD_ID); + + public MyMod(IEventBus modEventBus) { + // 在此处注册事件监听器 + // Register event listeners here + } +} +``` + +### 延迟初始化 / Lazy Initialization + +如果需要延迟初始化(避免在类加载阶段过早创建): +If you need lazy initialization to avoid creating too early during class loading: + +```java +public static final NonNullSupplier REGISTRATE = + NonNullSupplier.lazy(() -> Registrate.create(MOD_ID)); +``` + +## 注册你的第一个对象 / Registering Your First Object + +### 方块 / Block + +```java +public static final BlockEntry MY_BLOCK = REGISTRATE + .block("my_block", Block::new) + .simpleItem() // 自动创建 BlockItem / Automatically create a BlockItem + .defaultBlockstate() // 使用默认方块状态 / Use default blockstate + .defaultLang() // 自动生成语言条目 / Auto-generate lang entry + .defaultLoot() // 自动生成战利品表 / Auto-generate loot table + .register(); // 完成注册 / Finalize registration +``` + +### 物品 / Item + +```java +public static final ItemEntry MY_ITEM = REGISTRATE + .item("my_item", Item::new) + .defaultModel() // 使用默认模型 / Use default model + .defaultLang() // 自动生成语言条目 / Auto-generate lang entry + .register(); +``` + +### 方块实体 / Block Entity + +```java +public static final BlockEntityEntry MY_BE = REGISTRATE + .blockEntity("my_block_entity", MyBlockEntity::new) + .validBlock(() -> MyMod.MY_BLOCK) // 关联有效方块 / Associate valid block + .register(); +``` + +## 下一步 / Next Steps + +- 探索[构建器 API](builders.md) 了解所有可用的构建器和方法 + Explore the [builder API](builders.md) for all available builders and methods +- 查看[注册条目](entries.md)了解如何使用注册后的句柄 + Check [registry entries](entries.md) for how to use the registered handles +- 阅读[数据提供者](providers.md)了解自动数据生成系统 + Read about [data providers](providers.md) for the automatic data generation system diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..e46d845 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,45 @@ +# RegistrateLib 维基 / Wiki + +## 什么是 RegistrateLib? / What is RegistrateLib? + +RegistrateLib 是一个强大的流式注册 API 封装,用于在 NeoForge 模组中创建和注册对象。它提供了一套流畅的链式调用 API,让你能够以声明式的方式组织模组内容,并自动处理数据生成、本地化和标签管理。 + +RegistrateLib is a powerful fluent registration API wrapper for creating and registering objects in NeoForge mods. It provides a smooth chain-call API that lets you organize mod content declaratively, with automatic data generation, localization, and tag management. + +## 功能特性 / Features + +- **流畅的流式 API** — 链式调用构建器,以声明式方式定义对象及其行为 / Chain-call builders for declarative object definition +- **自动数据生成** — 自动为方块、物品、流体等生成模型、方块状态、战利品表和配方 / Automatic model, blockstate, loot table, and recipe generation +- **智能本地化** — 自动为注册对象生成语言条目 / Automatic lang entry generation for registered objects +- **标签管理** — 链式 API 中直接支持方块、物品、流体和实体标签 / Built-in tag support for blocks, items, fluids, and entities +- **自定义注册表** — 支持创建自定义注册表和数据包注册表 / Custom registry and datapack registry creation +- **创造模式标签页** — 轻松将物品分配到创造模式标签页 / Easy creative mode tab assignment + +## 快速开始 / Quick Start + +```java +// 创建 Registrate 实例 / Create a Registrate instance +public static final Registrate REGISTRATE = Registrate.create(MOD_ID); + +// 注册一个简单的方块 / Register a simple block +public static final BlockEntry MY_BLOCK = REGISTRATE.block("my_block", Block::new) + .simpleItem() + .register(); + +// 注册一个物品 / Register an item +public static final ItemEntry MY_ITEM = REGISTRATE.item("my_item", Item::new) + .register(); +``` + +## 文档目录 / Table of Contents + +1. [快速入门](getting-started.md) — 安装、设置和你的第一个注册 / Installation, setup, and your first registration +2. [构建器 API](builders.md) — 所有构建器的详细 API 参考 / Detailed builder API reference +3. [注册条目](entries.md) — 注册返回的强类型句柄 / Strongly-typed registry entry handles +4. [数据提供者](providers.md) — 数据生成系统详解 / Data generation system in detail +5. [高级用法](advanced.md) — 自定义注册表、生命周期钩子等 / Custom registries, lifecycle hooks, and more + +## 架构概述 / Architecture Overview + +详细信息请查阅 [architecture.md](architecture.md)。 +See [architecture.md](architecture.md) for package responsibilities and extension points. diff --git a/docs/providers.md b/docs/providers.md new file mode 100644 index 0000000..e7a8970 --- /dev/null +++ b/docs/providers.md @@ -0,0 +1,272 @@ +# 数据提供者 / Data Providers + +RegistrateLib 内置了自动数据生成系统。当你通过构建器注册对象时,它会自动收集数据生成任务,并在数据生成运行时统一输出。 + +RegistrateLib has a built-in automatic data generation system. When you register objects through builders, it automatically collects data generation tasks and outputs them uniformly during datagen runs. + +--- + +## 提供者类型 / Provider Types + +### 服务端提供者 / Server Providers + +| 类型 / Type | 类 / Class | 描述 / Description | +|--------------------|-------------------------------------------------------|----------------------------------------| +| `DYNAMIC` | `RegistrateDatapackProvider` | 动态数据包注册表 / Dynamic datapack registries | +| `DATA_MAP` | `RegistrateDataMapProvider` | 数据映射 / Data maps | +| `RECIPE_RUNNER` | `RegistrateRecipeRunner` | 配方(入口点)/ Recipes (entry point) | +| `ADVANCEMENT` | `RegistrateAdvancementProvider` | 进度 / Advancements | +| `LOOT` | `RegistrateLootTableProvider` | 战利品表 / Loot tables | +| `BLOCK_TAGS` | `RegistrateTagsProvider.IntrinsicImpl` | 方块标签 / Block tags | +| `ITEM_TAGS` | `RegistrateItemTagsProvider` | 物品标签 / Item tags | +| `FLUID_TAGS` | `RegistrateTagsProvider.IntrinsicImpl` | 流体标签 / Fluid tags | +| `ENTITY_TAGS` | `RegistrateTagsProvider.IntrinsicImpl>` | 实体标签 / Entity type tags | +| `ENCHANTMENT_TAGS` | `RegistrateTagsProvider.Impl` | 附魔标签 / Enchantment tags | +| `GENERIC_SERVER` | `RegistrateGenericProvider` | 通用服务端提供者 / Generic server provider | + +### 客户端提供者 / Client Providers + +| 类型 / Type | 类 / Class | 描述 / Description | +|------------------|-----------------------------|------------------------------------| +| `MODEL` | `RegistrateModelProvider` | 模型和方块状态 / Models & blockstates | +| `LANG` | `RegistrateLangProvider` | 语言文件(en_us + en_ud)/ Lang files | +| `GENERIC_CLIENT` | `RegistrateGenericProvider` | 通用客户端提供者 / Generic client provider | + +--- + +## 子生成器类型 / Sub-generator Types + +这些是更细粒度的生成器键,通常用于构建器的 `setData()` 方法。 +These are finer-grained generator keys, typically used in builder `.setData()`. + +| 生成器 / Generator | 所属提供者 / Parent Provider | 用途 / Purpose | +|-----------------|-------------------------|------------------------------------------------| +| `RECIPE` | `RECIPE_RUNNER` | 单个对象的配方生成 / Per-object recipe generation | +| `BLOCKSTATE` | `MODEL` | 单个对象的方块状态生成 / Per-object blockstate generation | +| `ITEM_MODEL` | `MODEL` | 单个对象的物品模型生成 / Per-object item model generation | + +--- + +## 构建器中集成数据生成 / Data Generation in Builders + +大多数构建器提供了直接的方法来配置数据生成: +Most builders provide direct methods to configure data generation: + +```java +// 方块 — 方块状态、模型、战利品、配方、语言 +// Block — blockstate, model, loot, recipe, lang +REGISTRATE.block("my_block", MyBlock::new) + .blockstate(ctx -> { /* ... */ }) // 方块状态 / blockstate + .loot((prov, block) -> { /* ... */ }) // 战利品表 / loot + .recipe((ctx, prov) -> { /* ... */ }) // 配方 / recipe + .lang("My Block") // 语言 / lang + .defaultBlockstate() // 使用默认值 / use defaults + .defaultLoot() + .register(); +``` + +--- + +## RegistrateLangProvider —— 语言提供者 / Lang Provider + +自动生成 `en_us` 和 `en_ud`(上下颠倒)语言文件。 +Automatically generates `en_us` and `en_ud` (upside-down) lang files. + +```java +// 通过 Registrate 添加语言条目 / Add lang entries via Registrate +REGISTRATE.addRawLang("key", "value"); // 原始语言键 / raw lang key +REGISTRATE.addLang("tooltip", blockId, "My Tooltip"); // 工具提示 / tooltip +REGISTRATE.addLang("item", itemId, "suffix", "Name"); // 带后缀的物品名称 / item name with suffix + +// 从构建器自动生成 / Auto-generated from builders +// 调用 .defaultLang() 或 .lang("name") 即可 / call .defaultLang() or .lang("name") +``` + +### 手动使用 / Manual Usage + +```java +// 直接访问语言提供者 / Access the lang provider directly +REGISTRATE.addDataGenerator(ProviderType.LANG, provider -> { + provider.addBlock(MY_BLOCK); + provider.addItem(MY_ITEM); + provider.addBlockWithTooltip(MY_BLOCK, "block.mymod.my_block", "A wonderful block"); +}); +``` + +--- + +## RegistrateTagsProvider —— 标签提供者 / Tag Provider + +标签管理可以通过构建器链式调用或在数据生成器中手动完成。 +Tag management can be done via builder chaining or manually in data generators. + +### 通过构建器 / Via Builders + +```java +REGISTRATE.block("my_block", Block::new) + .tag(BlockTags.STAIRS, BlockTags.DRAGON_IMMUNE) + .tag(BlockTags.WITHER_IMMUNE) + .register(); + +REGISTRATE.item("my_item", Item::new) + .tag(ItemTags.BEDS) + .register(); +``` + +### 手动使用 / Manual Usage + +```java +REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, provider -> { + provider.tag(ItemTags.STAIRS) + .add(MY_BLOCK.getKey()); +}); +``` + +### 复制方块标签到物品标签 / Copy Block Tags to Item Tags + +```java +// ItemTagsProvider 支持从方块标签复制到物品标签 +// ItemTagsProvider supports copying block tags to item tags +REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, provider -> { + provider.copy(BlockTags.STAIRS, ItemTags.STAIRS); +}); +``` + +--- + +## RegistrateRecipeProvider —— 配方提供者 / Recipe Provider + +在构建器中通过 `.recipe()` 添加配方: +Add recipes in builders via `.recipe()`: + +```java +REGISTRATE.block("my_block", MyBlock::new) + .recipe((ctx, prov) -> { + prov.shaped(RecipeCategory.MISC, ctx.getEntry()) + .pattern("DDD").pattern("DED").pattern("DDD") + .define('D', Items.DIAMOND) + .define('E', Items.EGG) + .unlockedBy("has_egg", prov.has(Items.EGG)) + .save(prov); + + prov.food(DataIngredient.items(ctx), RecipeCategory.MISC, + CookingBookCategory.MISC, () -> Blocks.DIAMOND_BLOCK, 1f); + }) + .register(); +``` + +### 便捷方法 / Convenience Methods + +| 方法 / Method | 描述 / Description | +|--------------------------------------------------------------------|-----------------------------------------------| +| `smelting(DataIngredient, RecipeCategory, NonNullSupplier, float)` | 烧炼配方 / Smelting recipe | +| `blasting(...)` | 高炉配方 / Blasting recipe | +| `smoking(...)` | 烟熏配方 / Smoking recipe | +| `campfire(...)` | 营火配方 / Campfire recipe | +| `stonecutting(...)` | 切石机配方 / Stonecutting recipe | +| `smeltingAndBlasting(...)` | 同时生成烧炼和高炉配方 / Both smelting & blasting | +| `food(...)` | 食物配方(烧炼)/ Food cooking recipe | +| `storage(...)` | 存储压缩配方(3x3 或 2x2)/ Storage compression recipe | +| `singleItem(...)` | 单物品配方 / Single item recipe | +| `planks(...)` | 木板配方 / Planks recipe | +| `stairs(...)` | 楼梯配方 / Stairs recipe | +| `slab(...)` | 台阶配方 / Slab recipe | +| `fence(...)` | 栅栏配方 / Fence recipe | +| `fenceGate(...)` | 栅栏门配方 / Fence gate recipe | +| `wall(...)` | 墙配方 / Wall recipe | +| `door(...)` | 门配方 / Door recipe | +| `trapDoor(...)` | 活板门配方 / Trapdoor recipe | + +--- + +## RegistrateLootTableProvider —— 战利品表提供者 / Loot Table Provider + +### 通过构建器 / Via Builders + +```java +REGISTRATE.block("my_block", MyBlock::new) + .loot((prov, block) -> { + prov.dropOther(block, Items.DIAMOND); + }) + .register(); + +REGISTRATE.entity("my_entity", MyEntity::new, MobCategory.CREATURE) + .loot((prov, type) -> { + prov.add(type, LootTable.lootTable() + .withPool(LootPool.lootPool() + .add(LootItem.lootTableItem(Items.DIAMOND) + .apply(SetItemCountFunction.setCount( + UniformGenerator.between(1, 3)))))); + }) + .register(); +``` + +### 可用方法 / Available Methods + +从 `RegistrateBlockLootTables`(继承自 `BlockLootSubProvider`): +From `RegistrateBlockLootTables` (extends `BlockLootSubProvider`): + +| 方法 / Method | 描述 / Description | +|---------------------------------------|----------------------------------------| +| `dropSelf(Block)` | 掉落自身 / Drop itself | +| `dropOther(Block, ItemLike)` | 掉落其他物品 / Drop other item | +| `createSingleItemTable(ItemLike)` | 单物品掉落表 / Single item drop table | +| `createSilkTouchDispatchTable(Block)` | 精准采集掉落表 / Silk touch drop table | +| `createSlabItemTable(Block)` | 台阶掉落表(保证掉落 2 个)/ Slab drop table | +| `createDoorTable(Block)` | 门掉落表 / Door drop table | +| `createOreDrop(Block, ItemLike)` | 矿石掉落 + 精准采集 / Ore drop with silk touch | + +--- + +## RegistrateAdvancementProvider —— 进度提供者 / Advancement Provider + +```java +REGISTRATE.addDataGenerator(ProviderType.ADVANCEMENT, adv -> { + Advancement.Builder.advancement() + .addCriterion("has_egg", + InventoryChangeTrigger.TriggerInstance.hasItems(Items.EGG)) + .display(Items.EGG, + adv.title(MOD_ID, "root", "Test Advancement"), + adv.desc(MOD_ID, "root", "Get an egg."), + Identifier.withDefaultNamespace( + "textures/gui/advancements/backgrounds/stone.png"), + AdvancementType.TASK, true, true, false) + .save(adv, MOD_ID + ":root"); +}); +``` + +--- + +## RegistrateGenericProvider —— 通用提供者 / Generic Provider + +用于自定义数据生成任务(服务端和客户端)。 +For custom data generation tasks (server and client). + +### 服务端示例:自定义维度 / Server Example: Custom Dimension + +```java +REGISTRATE.addDataGenerator(ProviderType.GENERIC_SERVER, + provider -> provider.add(data -> { + return new DatapackBuiltinEntriesProvider( + data.output(), data.registries(), + new RegistrySetBuilder() + .add(Registries.DIMENSION_TYPE, context -> { /* ... */ }) + .add(Registries.LEVEL_STEM, context -> { /* ... */ }), + Set.of(MOD_ID)); + })); +``` + +--- + +## 注册自定义提供者 / Registering Custom Providers + +你可以通过 `ProviderType.registerServerData()` 和 `ProviderType.registerClientProvider()` 注册自己的提供者类型。 + +You can register your own provider types via `ProviderType.registerServerData()` and `ProviderType.registerClientProvider()`. + +```java +// 注册自定义服务端数据提供者 +// Register a custom server data provider +public static final ProviderType MY_PROVIDER = + ProviderType.registerServerData("my_provider", MyCustomProvider::new); +``` From 12c9f79ea767d0e7ab65e63b37eeb63d1988ad12 Mon Sep 17 00:00:00 2001 From: qiuye2024github Date: Wed, 29 Apr 2026 20:24:48 +0800 Subject: [PATCH 2/3] fix --- .github/workflows/manage-pr-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manage-pr-labels.yml b/.github/workflows/manage-pr-labels.yml index 80c2e0c..98b2026 100644 --- a/.github/workflows/manage-pr-labels.yml +++ b/.github/workflows/manage-pr-labels.yml @@ -30,7 +30,7 @@ jobs: with: mode: minimum count: 1 - labels: 'type: feature, type: bugfix, type: refactor, type: translation, type: tests, ignore changelog' + labels: 'type: feature, type: bugfix, type: refactor, type: translation, type: tests, type: documentation, ignore changelog' exit_type: failure - name: Check for Required Release Label # require exactly one of these labels From a55abd90bbaa12edc4f4b89665673fadd9c5a954 Mon Sep 17 00:00:00 2001 From: qiuye2024github Date: Wed, 29 Apr 2026 20:31:44 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix=20=E5=B7=A5=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/manage-pr-labels.yml | 64 +++++++++++++------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/manage-pr-labels.yml b/.github/workflows/manage-pr-labels.yml index 98b2026..c0dc5b6 100644 --- a/.github/workflows/manage-pr-labels.yml +++ b/.github/workflows/manage-pr-labels.yml @@ -3,41 +3,41 @@ name: Pull Request Labels # Checks for label once PR has been reviewed or label is applied on: - pull_request: - types: [opened, labeled, unlabeled] + pull_request: + types: [opened, labeled, unlabeled] concurrency: - group: pr-labels-${{ github.head_ref }} - cancel-in-progress: true + group: pr-labels-${{ github.head_ref }} + cancel-in-progress: true jobs: - labels: - name: Label Check - runs-on: ubuntu-latest - permissions: - pull-requests: read # needed to utilize required-labels - steps: - - name: Check for Merge-Blocking Labels # blocks merge if present - uses: mheap/github-action-required-labels@v5 - with: - mode: exactly - count: 0 - labels: 'do not merge, admin merge' - exit_type: failure + labels: + name: Label Check + runs-on: ubuntu-latest + permissions: + pull-requests: read # needed to utilize required-labels + steps: + - name: Check for Merge-Blocking Labels # blocks merge if present + uses: mheap/github-action-required-labels@v5 + with: + mode: exactly + count: 0 + labels: 'do not merge, admin merge' + exit_type: failure - - name: Check for Required Type Labels # require at least one of these labels - uses: mheap/github-action-required-labels@v5 - with: - mode: minimum - count: 1 - labels: 'type: feature, type: bugfix, type: refactor, type: translation, type: tests, type: documentation, ignore changelog' - exit_type: failure + - name: Check for Required Type Labels # require at least one of these labels + uses: mheap/github-action-required-labels@v5 + with: + mode: minimum + count: 1 + labels: 'type: feature, type: bugfix, type: refactor, type: translation, type: tests, ignore changelog' + exit_type: failure + + - name: Check for Required Release Label # require exactly one of these labels + uses: mheap/github-action-required-labels@v5 + with: + mode: exactly + count: 1 + labels: 'release: api - X.0.0, release: major - 0.X.0, release: Patch - 0.0.X, release: stale' + exit_type: failure - - name: Check for Required Release Label # require exactly one of these labels - uses: mheap/github-action-required-labels@v5 - with: - mode: exactly - count: 1 - labels: 'release: api - X.0.0, release: major - 0.X.0, release: Patch - 0.0.X, release: stale' - exit_type: failure -