Support extending dynamic registries in datagen ()

- Add all dynamic registries to the initial registry.
 - Expose a getter for the registry future.
 - Register cloners for all dynamic registries.

(cherry picked from commit ad4744939b)
This commit is contained in:
Jonathan Coates 2024-05-07 19:04:02 +01:00 committed by modmuss50
parent 186cc2ef8b
commit 1c4a86e83a
6 changed files with 96 additions and 1 deletions
fabric-data-generation-api-v1/src
main/java/net/fabricmc/fabric
testmod/java/net/fabricmc/fabric/test/datagen
fabric-registry-sync-v0/src/main
java/net/fabricmc/fabric/mixin/registry/sync
resources

View file

@ -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()}
*/

View file

@ -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)

View file

@ -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"));

View file

@ -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);

View file

@ -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();
}
}

View file

@ -6,6 +6,7 @@
"BootstrapMixin",
"ChunkSerializerMixin",
"DebugChunkGeneratorAccessor",
"ExperimentalRegistriesValidatorMixin",
"IdListMixin",
"MinecraftServerMixin",
"RegistriesAccessor",