diff --git a/patches/minecraft/net/minecraft/data/registries/RegistriesDatapackGenerator.java.patch b/patches/minecraft/net/minecraft/data/registries/RegistriesDatapackGenerator.java.patch index 0a656435d0..6e1533edc9 100644 --- a/patches/minecraft/net/minecraft/data/registries/RegistriesDatapackGenerator.java.patch +++ b/patches/minecraft/net/minecraft/data/registries/RegistriesDatapackGenerator.java.patch @@ -25,7 +25,7 @@ return this.registries.thenCompose((p_256533_) -> { DynamicOps dynamicops = RegistryOps.create(JsonOps.INSTANCE, p_256533_); - return CompletableFuture.allOf(RegistryDataLoader.WORLDGEN_REGISTRIES.stream().flatMap((p_256552_) -> { -+ return CompletableFuture.allOf(net.minecraftforge.registries.DataPackRegistriesHooks.getDataPackRegistriesWithDimensions().flatMap((p_256552_) -> { ++ return CompletableFuture.allOf(RegistryDataLoader.getWorldGenAndDimensionStream().flatMap((p_256552_) -> { return this.dumpRegistryCap(p_255785_, p_256533_, dynamicops, p_256552_).stream(); }).toArray((p_255809_) -> { return new CompletableFuture[p_255809_]; diff --git a/patches/minecraft/net/minecraft/data/registries/RegistryPatchGenerator.java.patch b/patches/minecraft/net/minecraft/data/registries/RegistryPatchGenerator.java.patch index 36cbef677b..ca01c44ae9 100644 --- a/patches/minecraft/net/minecraft/data/registries/RegistryPatchGenerator.java.patch +++ b/patches/minecraft/net/minecraft/data/registries/RegistryPatchGenerator.java.patch @@ -1,10 +1,11 @@ --- a/net/minecraft/data/registries/RegistryPatchGenerator.java +++ b/net/minecraft/data/registries/RegistryPatchGenerator.java -@@ -20,6 +_,7 @@ - RegistryDataLoader.WORLDGEN_REGISTRIES.forEach((p_313050_) -> { +@@ -17,7 +_,7 @@ + return p_310881_.thenApply((p_309945_) -> { + RegistryAccess.Frozen registryaccess$frozen = RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY); + Cloner.Factory cloner$factory = new Cloner.Factory(); +- RegistryDataLoader.WORLDGEN_REGISTRIES.forEach((p_313050_) -> { ++ RegistryDataLoader.getWorldGenAndDimensionStream().forEach((p_313050_) -> { p_313050_.runWithArguments(cloner$factory::addCodec); }); -+ RegistryDataLoader.DIMENSION_REGISTRIES.forEach(reg -> reg.runWithArguments(cloner$factory::addCodec)); RegistrySetBuilder.PatchedRegistries registrysetbuilder$patchedregistries = p_310262_.buildPatch(registryaccess$frozen, p_309945_, cloner$factory); - HolderLookup.Provider holderlookup$provider = registrysetbuilder$patchedregistries.full(); - Optional> optional = holderlookup$provider.lookup(Registries.BIOME); diff --git a/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch b/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch index ce0ad31a67..5ca2734aea 100644 --- a/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch +++ b/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch @@ -1,5 +1,20 @@ --- a/net/minecraft/resources/RegistryDataLoader.java +++ b/net/minecraft/resources/RegistryDataLoader.java +@@ -51,9 +_,13 @@ + + public class RegistryDataLoader { + private static final Logger LOGGER = LogUtils.getLogger(); +- public static final List> WORLDGEN_REGISTRIES = List.of(new RegistryDataLoader.RegistryData<>(Registries.DIMENSION_TYPE, DimensionType.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.BIOME, Biome.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.CHAT_TYPE, ChatType.CODEC), new RegistryDataLoader.RegistryData<>(Registries.CONFIGURED_CARVER, ConfiguredWorldCarver.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.CONFIGURED_FEATURE, ConfiguredFeature.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.PLACED_FEATURE, PlacedFeature.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.STRUCTURE, Structure.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.STRUCTURE_SET, StructureSet.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.PROCESSOR_LIST, StructureProcessorType.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TEMPLATE_POOL, StructureTemplatePool.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.NOISE_SETTINGS, NoiseGeneratorSettings.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.NOISE, NormalNoise.NoiseParameters.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.DENSITY_FUNCTION, DensityFunction.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.WORLD_PRESET, WorldPreset.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.FLAT_LEVEL_GENERATOR_PRESET, FlatLevelGeneratorPreset.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TRIM_PATTERN, TrimPattern.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TRIM_MATERIAL, TrimMaterial.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.DAMAGE_TYPE, DamageType.CODEC), new RegistryDataLoader.RegistryData<>(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, MultiNoiseBiomeSourceParameterList.DIRECT_CODEC)); ++ public static final List> WORLDGEN_REGISTRIES = net.minecraftforge.registries.DataPackRegistriesHooks.grabWorldgenRegistries(new RegistryDataLoader.RegistryData<>(Registries.DIMENSION_TYPE, DimensionType.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.BIOME, Biome.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.CHAT_TYPE, ChatType.CODEC), new RegistryDataLoader.RegistryData<>(Registries.CONFIGURED_CARVER, ConfiguredWorldCarver.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.CONFIGURED_FEATURE, ConfiguredFeature.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.PLACED_FEATURE, PlacedFeature.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.STRUCTURE, Structure.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.STRUCTURE_SET, StructureSet.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.PROCESSOR_LIST, StructureProcessorType.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TEMPLATE_POOL, StructureTemplatePool.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.NOISE_SETTINGS, NoiseGeneratorSettings.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.NOISE, NormalNoise.NoiseParameters.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.DENSITY_FUNCTION, DensityFunction.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.WORLD_PRESET, WorldPreset.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.FLAT_LEVEL_GENERATOR_PRESET, FlatLevelGeneratorPreset.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TRIM_PATTERN, TrimPattern.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.TRIM_MATERIAL, TrimMaterial.DIRECT_CODEC), new RegistryDataLoader.RegistryData<>(Registries.DAMAGE_TYPE, DamageType.CODEC), new RegistryDataLoader.RegistryData<>(Registries.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, MultiNoiseBiomeSourceParameterList.DIRECT_CODEC)); + public static final List> DIMENSION_REGISTRIES = List.of(new RegistryDataLoader.RegistryData<>(Registries.LEVEL_STEM, LevelStem.CODEC)); + ++ public static java.util.stream.Stream> getWorldGenAndDimensionStream() { ++ return java.util.stream.Stream.concat(RegistryDataLoader.WORLDGEN_REGISTRIES.stream(), RegistryDataLoader.DIMENSION_REGISTRIES.stream()); ++ } ++ + public static RegistryAccess.Frozen load(ResourceManager p_252046_, RegistryAccess p_249916_, List> p_250344_) { + Map, Exception> map = new HashMap<>(); + List, RegistryDataLoader.Loader>> list = p_250344_.stream().map((p_250249_) -> { @@ -75,7 +_,9 @@ }); if (!map.isEmpty()) { diff --git a/patches/minecraft/net/minecraft/server/WorldLoader.java.patch b/patches/minecraft/net/minecraft/server/WorldLoader.java.patch deleted file mode 100644 index b88d6a1ca9..0000000000 --- a/patches/minecraft/net/minecraft/server/WorldLoader.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/minecraft/server/WorldLoader.java -+++ b/net/minecraft/server/WorldLoader.java -@@ -28,7 +_,7 @@ - Pair pair = p_214363_.packConfig.createResourceManager(); - CloseableResourceManager closeableresourcemanager = pair.getSecond(); - LayeredRegistryAccess layeredregistryaccess = RegistryLayer.createRegistryAccess(); -- LayeredRegistryAccess layeredregistryaccess1 = loadAndReplaceLayer(closeableresourcemanager, layeredregistryaccess, RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES); -+ LayeredRegistryAccess layeredregistryaccess1 = loadAndReplaceLayer(closeableresourcemanager, layeredregistryaccess, RegistryLayer.WORLDGEN, net.minecraftforge.registries.DataPackRegistriesHooks.getDataPackRegistries()); - RegistryAccess.Frozen registryaccess$frozen = layeredregistryaccess1.getAccessForLoading(RegistryLayer.DIMENSIONS); - RegistryAccess.Frozen registryaccess$frozen1 = RegistryDataLoader.load(closeableresourcemanager, registryaccess$frozen, RegistryDataLoader.DIMENSION_REGISTRIES); - WorldDataConfiguration worlddataconfiguration = pair.getFirst(); diff --git a/src/main/java/net/minecraftforge/registries/DataPackRegistriesHooks.java b/src/main/java/net/minecraftforge/registries/DataPackRegistriesHooks.java index 3138464131..867d9b563d 100644 --- a/src/main/java/net/minecraftforge/registries/DataPackRegistriesHooks.java +++ b/src/main/java/net/minecraftforge/registries/DataPackRegistriesHooks.java @@ -12,13 +12,7 @@ import net.minecraft.resources.RegistryDataLoader; import net.minecraft.resources.ResourceKey; import org.jetbrains.annotations.ApiStatus; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Stream; @ApiStatus.Internal @@ -26,8 +20,7 @@ public final class DataPackRegistriesHooks { private DataPackRegistriesHooks() {} // utility class private static final Map>, RegistrySynchronization.NetworkedRegistryData> NETWORKABLE_REGISTRIES = new LinkedHashMap<>(); - private static final List> DATA_PACK_REGISTRIES = new ArrayList<>(RegistryDataLoader.WORLDGEN_REGISTRIES); - private static final List> DATA_PACK_REGISTRIES_VIEW = Collections.unmodifiableList(DATA_PACK_REGISTRIES); + private static final List> WORLDGEN_REGISTRIES = new ArrayList<>(); private static final Set>> SYNCED_CUSTOM_REGISTRIES = new HashSet<>(); private static final Set>> SYNCED_CUSTOM_REGISTRIES_VIEW = Collections.unmodifiableSet(SYNCED_CUSTOM_REGISTRIES); @@ -44,7 +37,7 @@ public final class DataPackRegistriesHooks { /* Internal forge method, registers a datapack registry codec and folder. */ static void addRegistryCodec(DataPackRegistryEvent.DataPackRegistryData data) { RegistryDataLoader.RegistryData loaderData = data.loaderData(); - DATA_PACK_REGISTRIES.add(loaderData); + WORLDGEN_REGISTRIES.add(loaderData); if (data.networkCodec() != null) { SYNCED_CUSTOM_REGISTRIES.add(loaderData.key()); NETWORKABLE_REGISTRIES.put(loaderData.key(), new RegistrySynchronization.NetworkedRegistryData<>(loaderData.key(), data.networkCodec())); @@ -55,12 +48,27 @@ public final class DataPackRegistriesHooks { * {@return An unmodifiable view of the list of datapack registries}. * These registries are loaded from per-world datapacks on server startup. */ + @Deprecated // Use RegistryDataLoader#WORLDGEN_REGISTRIES instead public static List> getDataPackRegistries() { - return DATA_PACK_REGISTRIES_VIEW; + return Collections.unmodifiableList(WORLDGEN_REGISTRIES); } + @Deprecated // Use RegistryDataLoader#WORLDGEN_REGISTRIES instead public static Stream> getDataPackRegistriesWithDimensions() { - return Stream.concat(DATA_PACK_REGISTRIES_VIEW.stream(), RegistryDataLoader.DIMENSION_REGISTRIES.stream()); + return WORLDGEN_REGISTRIES.stream(); + } + + /** + * Captures a mutable view of {@link RegistryDataLoader#WORLDGEN_REGISTRIES} so that we can register modded entries during the registry event. + * All uses should use that field instead of this class. + * @param vanilla The vanilla worldgen registries + * @return An unmodifiable list of worldgen registries + */ + public static List> grabWorldgenRegistries(RegistryDataLoader.RegistryData... vanilla) { + if (!StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass().equals(RegistryDataLoader.class)) + throw new IllegalCallerException("Attempted to call DataPackRegistriesHooks#grabWorldgenRegistries!"); + WORLDGEN_REGISTRIES.addAll(Arrays.asList(vanilla)); + return Collections.unmodifiableList(WORLDGEN_REGISTRIES); } /** diff --git a/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/biome_modifier/mossy_stone_modifier.json b/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/biome_modifier/mossy_stone_modifier.json new file mode 100644 index 0000000000..e84a3fe877 --- /dev/null +++ b/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/biome_modifier/mossy_stone_modifier.json @@ -0,0 +1,6 @@ +{ + "type": "forge:add_features", + "biomes": "#minecraft:is_overworld", + "features": "datapack_builtin_entries_provider_test:mossy_stone", + "step": "underground_ores" +} \ No newline at end of file diff --git a/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/worldgen/configured_feature/mossy_stone.json b/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/worldgen/configured_feature/mossy_stone.json new file mode 100644 index 0000000000..417d81d442 --- /dev/null +++ b/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/worldgen/configured_feature/mossy_stone.json @@ -0,0 +1,27 @@ +{ + "type": "minecraft:ore", + "config": { + "discard_chance_on_air_exposure": 0.0, + "size": 5, + "targets": [ + { + "state": { + "Name": "minecraft:mossy_cobblestone" + }, + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "minecraft:stone_ore_replaceables" + } + }, + { + "state": { + "Name": "minecraft:mossy_cobblestone" + }, + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "minecraft:deepslate_ore_replaceables" + } + } + ] + } +} \ No newline at end of file diff --git a/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/worldgen/placed_feature/mossy_stone.json b/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/worldgen/placed_feature/mossy_stone.json new file mode 100644 index 0000000000..cfd8ace2f6 --- /dev/null +++ b/src/test/generated/datapack_builtin_entries_provider_test/data/datapack_builtin_entries_provider_test/worldgen/placed_feature/mossy_stone.json @@ -0,0 +1,27 @@ +{ + "feature": "datapack_builtin_entries_provider_test:mossy_stone", + "placement": [ + { + "type": "minecraft:count", + "count": 8 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:uniform", + "max_inclusive": { + "absolute": 64 + }, + "min_inclusive": { + "absolute": -64 + } + } + }, + { + "type": "minecraft:biome" + } + ] +} \ No newline at end of file diff --git a/src/test/java/net/minecraftforge/debug/gameplay/data/DatapackBuiltinEntriesProviderTest.java b/src/test/java/net/minecraftforge/debug/gameplay/data/DatapackBuiltinEntriesProviderTest.java new file mode 100644 index 0000000000..758b24f5f2 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/gameplay/data/DatapackBuiltinEntriesProviderTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.debug.gameplay.data; + +import net.minecraft.DetectedVersion; +import net.minecraft.core.*; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.metadata.PackMetadataGenerator; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.metadata.pack.PackMetadataSection; +import net.minecraft.tags.BiomeTags; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; +import net.minecraft.world.level.levelgen.placement.*; +import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest; +import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider; +import net.minecraftforge.common.world.BiomeModifier; +import net.minecraftforge.common.world.ForgeBiomeModifiers; +import net.minecraftforge.data.event.GatherDataEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.test.BaseTestMod; + +import java.util.*; +import java.util.function.Supplier; + +@Mod(DatapackBuiltinEntriesProviderTest.MOD_ID) +public class DatapackBuiltinEntriesProviderTest extends BaseTestMod { + + public static final String MOD_ID = "datapack_builtin_entries_provider_test"; + // Vanilla registry entries + public static final ResourceKey> MOSSY_STONE_FEATURE = ResourceKey.create(Registries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "mossy_stone")); + public static final ResourceKey MOSSY_STONE_PLACEMENT = ResourceKey.create(Registries.PLACED_FEATURE, new ResourceLocation(MOD_ID, "mossy_stone")); + // Forge registry entries + public static final ResourceKey MOSSY_STONE_MODIFIER = ResourceKey.create(ForgeRegistries.Keys.BIOME_MODIFIERS, new ResourceLocation(MOD_ID, "mossy_stone_modifier")); + // The ore targets + public static final Supplier> MOSSY_STONE_TARGETS = () -> { + return List.of( + OreConfiguration.target(new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES), Blocks.MOSSY_COBBLESTONE.defaultBlockState()), + OreConfiguration.target(new TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES), Blocks.MOSSY_COBBLESTONE.defaultBlockState()) + ); + }; + + @SubscribeEvent + public void onDataGen(GatherDataEvent event) { + var gen = event.getGenerator(); + var packOutput = gen.getPackOutput(); + /* Adds the DataPackBuiltinEntriesProvider to the data generator + * If the registry is not correctly patched (it does only include the vanilla registries), the provider will fail with an exception + * Reason: The RegistrySetBuilder creates a full patched registry including a lookup for all registries + * For the lookup a cloner is needed, which is not available for forge registries + */ + gen.addProvider(event.includeServer(), new DatapackBuiltinEntriesProvider(packOutput, event.getLookupProvider(), this.createProvider(), Set.of(MOD_ID))); + } + + // Creates the registry builder for 2 vanilla and 1 forge registry + private RegistrySetBuilder createProvider() { + var builder = new RegistrySetBuilder(); + builder.add(Registries.CONFIGURED_FEATURE, c -> this.createFeature(c)); + builder.add(Registries.PLACED_FEATURE, this::createPlacement); + builder.add(ForgeRegistries.Keys.BIOME_MODIFIERS, this::createModifier); + return builder; + } + + // Registers the mossy stone feature + private void createFeature(BootstapContext> context) { + context.register(MOSSY_STONE_FEATURE, new ConfiguredFeature<>( + Feature.ORE, + new OreConfiguration(MOSSY_STONE_TARGETS.get(), 5) + )); + } + + // Registers the mossy stone placement + private void createPlacement(BootstapContext context) { + HolderGetter> featureRegistry = context.lookup(Registries.CONFIGURED_FEATURE); + context.register(MOSSY_STONE_PLACEMENT, new PlacedFeature( + featureRegistry.getOrThrow(MOSSY_STONE_FEATURE), + List.of(CountPlacement.of(8), InSquarePlacement.spread(), HeightRangePlacement.uniform(VerticalAnchor.absolute(-64), VerticalAnchor.absolute(64)), BiomeFilter.biome()) + )); + } + + // Registers the mossy stone biome modifier + private void createModifier(BootstapContext context) { + HolderGetter biomeRegistry = context.lookup(Registries.BIOME); + HolderGetter placementRegistry = context.lookup(Registries.PLACED_FEATURE); + context.register(MOSSY_STONE_MODIFIER, new ForgeBiomeModifiers.AddFeaturesBiomeModifier( + biomeRegistry.getOrThrow(BiomeTags.IS_OVERWORLD), + HolderSet.direct(placementRegistry.getOrThrow(MOSSY_STONE_PLACEMENT)), + GenerationStep.Decoration.UNDERGROUND_ORES + )); + } +}