diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java index 0cbe39421..6105255c5 100644 --- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/FabricDataGenerator.java @@ -25,6 +25,9 @@ import org.jetbrains.annotations.ApiStatus; import net.minecraft.SharedConstants; import net.minecraft.data.DataGenerator; import net.minecraft.data.DataProvider; +import net.minecraft.registry.BuiltinRegistries; +import net.minecraft.registry.ExperimentalRegistriesValidator; +import net.minecraft.registry.RegistryBuilder; import net.minecraft.registry.RegistryWrapper; import net.minecraft.util.Identifier; @@ -95,6 +98,20 @@ public final class FabricDataGenerator extends DataGenerator { return strictValidation; } + /** + * Get a future returning the default registries produced by {@link BuiltinRegistries} and + * {@link DataGeneratorEntrypoint#buildRegistry(RegistryBuilder)}. + * + * <p>Generally one does not need direct access to the registries, and instead can pass them directly to a + * {@link DataProvider} by using {@link Pack#addProvider(Pack.RegistryDependentFactory)}. However, this method may + * be useful when extending the vanilla registries (such as with {@link ExperimentalRegistriesValidator}). + * + * @return A future containing the builtin registries. + */ + public CompletableFuture<RegistryWrapper.WrapperLookup> getRegistries() { + return registriesFuture; + } + /** * @deprecated Please use {@link FabricDataGenerator#createPack()} */ diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java index 3a00e7193..edee955b3 100644 --- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java @@ -45,11 +45,13 @@ import net.minecraft.registry.Registerable; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryBuilder; import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryLoader; import net.minecraft.registry.RegistryWrapper; import net.minecraft.util.Util; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; +import net.fabricmc.fabric.api.event.registry.DynamicRegistries; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions; import net.fabricmc.loader.api.FabricLoader; @@ -176,7 +178,7 @@ public final class FabricDataGenHelper { BuilderData(RegistryKey key) { this.key = key; this.bootstrapFunctions = new ArrayList<>(); - this.lifecycle = null; + this.lifecycle = Lifecycle.stable(); } void with(RegistryBuilder.RegistryInfo<?> registryInfo) { @@ -197,6 +199,11 @@ public final class FabricDataGenHelper { Map<RegistryKey<?>, BuilderData> builderDataMap = new HashMap<>(); + // Ensure all dynamic registries are present. + for (RegistryLoader.Entry<?> key : DynamicRegistries.getDynamicRegistries()) { + builderDataMap.computeIfAbsent(key.key(), BuilderData::new); + } + for (RegistryBuilder builder : builders) { for (RegistryBuilder.RegistryInfo<?> info : builder.registries) { builderDataMap.computeIfAbsent(info.key(), BuilderData::new) diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java index b367cc057..bdb921f38 100644 --- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java +++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java @@ -56,6 +56,10 @@ public class DataGeneratorTestContent implements ModInitializer { TEST_DATAGEN_DYNAMIC_REGISTRY_KEY, new Identifier(MOD_ID, "tiny_potato") ); + public static final RegistryKey<TestDatagenObject> TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY = RegistryKey.of( + TEST_DATAGEN_DYNAMIC_REGISTRY_KEY, + new Identifier(MOD_ID, "tinier_potato") + ); // Empty registry public static final RegistryKey<Registry<TestDatagenObject>> TEST_DATAGEN_DYNAMIC_EMPTY_REGISTRY_KEY = RegistryKey.ofRegistry(new Identifier("fabric", "test_datagen_dynamic_empty")); diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java index 77b2f375c..a14c37ac4 100644 --- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java +++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java @@ -24,6 +24,7 @@ import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.MOD_ID; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_BLOCK; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_ITEM_GROUP; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DATAGEN_DYNAMIC_REGISTRY_KEY; +import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DYNAMIC_REGISTRY_ITEM_KEY; import java.io.IOException; @@ -63,6 +64,7 @@ import net.minecraft.loot.entry.ItemEntry; import net.minecraft.loot.provider.number.ConstantLootNumberProvider; import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.book.RecipeCategory; +import net.minecraft.registry.ExperimentalRegistriesValidator; import net.minecraft.registry.Registerable; import net.minecraft.registry.Registries; import net.minecraft.registry.RegistryBuilder; @@ -139,6 +141,14 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint { throw new RuntimeException(e); } } + + FabricDataGenerator.Pack extraPack = dataGenerator.createBuiltinResourcePack(new Identifier(MOD_ID, "extra")); + CompletableFuture<RegistryWrapper.WrapperLookup> extraRegistries = ExperimentalRegistriesValidator.validate(dataGenerator.getRegistries(), new RegistryBuilder() + .addRegistry(TEST_DATAGEN_DYNAMIC_REGISTRY_KEY, c -> + c.register(TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY, new DataGeneratorTestContent.TestDatagenObject(":tiny_potato:")) + ) + ).thenApply(RegistryBuilder.FullPatchesRegistriesPair::full); + extraPack.addProvider((FabricDataOutput out) -> new TestExtraDynamicRegistryProvider(out, extraRegistries)); } @Override @@ -432,6 +442,25 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint { } } + /** + * Test generating files for a patched/extended dynamic registry. + */ + private static class TestExtraDynamicRegistryProvider extends FabricDynamicRegistryProvider { + TestExtraDynamicRegistryProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) { + super(output, registriesFuture); + } + + @Override + protected void configure(RegistryWrapper.WrapperLookup registries, Entries entries) { + entries.add(registries.getWrapperOrThrow(TEST_DATAGEN_DYNAMIC_REGISTRY_KEY), TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY); + } + + @Override + public String getName() { + return "Test Dynamic Registry"; + } + } + private static class TestPredicateProvider extends FabricCodecDataProvider<LootCondition> { private TestPredicateProvider(FabricDataOutput dataOutput, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) { super(dataOutput, registriesFuture, DataOutput.OutputType.DATA_PACK, "predicates", LootCondition.CODEC); diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/ExperimentalRegistriesValidatorMixin.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/ExperimentalRegistriesValidatorMixin.java new file mode 100644 index 000000000..e59c36f37 --- /dev/null +++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/ExperimentalRegistriesValidatorMixin.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.registry.sync; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.registry.ExperimentalRegistriesValidator; +import net.minecraft.registry.RegistryLoader; + +import net.fabricmc.fabric.api.event.registry.DynamicRegistries; + +@Mixin(ExperimentalRegistriesValidator.class) +class ExperimentalRegistriesValidatorMixin { + @Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/registry/RegistryLoader;DYNAMIC_REGISTRIES:Ljava/util/List;"), method = "method_54839") + private static List<RegistryLoader.Entry<?>> getDynamicRegistries() { + // Register cloners for all dynamic registries. + return DynamicRegistries.getDynamicRegistries(); + } +} diff --git a/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json b/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json index 36ddad626..c3e629e5a 100644 --- a/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json +++ b/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json @@ -6,6 +6,7 @@ "BootstrapMixin", "ChunkSerializerMixin", "DebugChunkGeneratorAccessor", + "ExperimentalRegistriesValidatorMixin", "IdListMixin", "MinecraftServerMixin", "RegistriesAccessor",