@@ -388,9 +388,15 @@ private DatapackWorldgen(CloseableResourceManager resourceManager, RegistryAcces
388388 }
389389
390390 public static DatapackWorldgen load (Path datapackRoot , long seed ) throws IOException {
391- PackResources vanilla = createVanillaPack ();
392- PackResources customPack = createPathPack ("seedmapper_datapack" , datapackRoot , PackSource .WORLD );
393- CloseableResourceManager resourceManager = new MultiPackResourceManager (PackType .SERVER_DATA , List .of (vanilla , customPack ));
391+ PackResources vanilla = createVanillaPack ();
392+ // Create a sanitized copy of the datapack that strips worldgen JSON which
393+ // commonly fails registry loading (noise_settings, density_function, etc.).
394+ Path sanitized = sanitizeDatapack (datapackRoot );
395+ PackResources customPack = createPathPack ("seedmapper_datapack" , sanitized , PackSource .WORLD );
396+ // Create a small runtime fallback datapack to supply missing density-function keys
397+ Path fallbackDatapack = createTemporaryFallbackDatapack ();
398+ PackResources fallbackPack = createPathPack ("seedmapper_fallback" , fallbackDatapack , PackSource .BUILT_IN );
399+ CloseableResourceManager resourceManager = new MultiPackResourceManager (PackType .SERVER_DATA , List .of (vanilla , fallbackPack , customPack ));
394400 RegistryAccess .Frozen registryAccess = loadRegistryAccess (resourceManager );
395401 Set <Identifier > vanillaStructures = loadVanillaStructureIds ();
396402 LevelStorageSource .LevelStorageAccess storageAccess = createTempStorageAccess ();
@@ -604,6 +610,45 @@ private static List<CustomStructureSet> buildCustomStructureSets(RegistryAccess
604610 }
605611 }
606612
613+ private static Path createTemporaryFallbackDatapack () throws IOException {
614+ Path temp = Files .createTempDirectory ("seedmapper_fallback_datapack" );
615+ Path dataDir = temp .resolve ("data" ).resolve ("minecraft" ).resolve ("worldgen" ).resolve ("density_function" );
616+ Files .createDirectories (dataDir );
617+ // Provide a simple constant density function so registry parsing that expects
618+ // `preliminary_surface_level` can resolve during datapack import. This is
619+ // intentionally minimal; it acts as a fallback only.
620+ String json = "{\n \" type\" : \" minecraft:constant\" ,\n \" argument\" : 64.0\n }\n " ;
621+ Files .writeString (dataDir .resolve ("preliminary_surface_level.json" ), json );
622+ return temp ;
623+ }
624+
625+ private static Path sanitizeDatapack (Path baseDir ) throws IOException {
626+ if (baseDir == null ) return null ;
627+ Path sanitized = Files .createTempDirectory ("seedmapper_sanitized_" );
628+ try (Stream <Path > stream = Files .walk (baseDir )) {
629+ stream .forEach (source -> {
630+ try {
631+ Path rel = baseDir .relativize (source );
632+ String relStr = rel .toString ().replace ('\\' , '/' );
633+ // Skip worldgen-related files under data/*/worldgen/**
634+ if (relStr .startsWith ("data/" ) && relStr .contains ("/worldgen/" )) {
635+ return ;
636+ }
637+ Path target = sanitized .resolve (rel );
638+ if (Files .isDirectory (source )) {
639+ Files .createDirectories (target );
640+ } else {
641+ Files .createDirectories (target .getParent ());
642+ Files .copy (source , target , StandardCopyOption .REPLACE_EXISTING );
643+ }
644+ } catch (IOException e ) {
645+ throw new RuntimeException (e );
646+ }
647+ });
648+ }
649+ return sanitized ;
650+ }
651+
607652 public record DimensionContext (int dimensionId , ChunkGenerator chunkGenerator , BiomeSource biomeSource , RandomState randomState ,
608653 ChunkGeneratorStructureState structureState , LevelHeightAccessor heightAccessor ) {}
609654
@@ -927,6 +972,29 @@ private static RegistryAccess.Frozen loadRegistryAccess(ResourceManager resource
927972 new FilteringResourceManager (resourceManager , DatapackStructureManager ::isEnchantmentRelatedResource ),
928973 DatapackStructureManager ::isEnchantmentRelatedRegistry
929974 ),
975+ new RegistryLoadAttempt (
976+ "skip_worldgen_noise_and_density" ,
977+ resourceManager ,
978+ key -> {
979+ if (key == null ) return false ;
980+ // Avoid loading worldgen noise settings and density functions from the datapack
981+ if (Registries .NOISE_SETTINGS .equals (key ) || Registries .DENSITY_FUNCTION .equals (key )) return false ;
982+ return true ;
983+ }
984+ ),
985+ new RegistryLoadAttempt (
986+ "structures_only" ,
987+ new FilteringResourceManager (resourceManager , DatapackStructureManager ::isWorldgenResource ),
988+ key -> {
989+ if (key == null ) return false ;
990+ return Registries .STRUCTURE .equals (key )
991+ || Registries .STRUCTURE_SET .equals (key )
992+ || Registries .BIOME .equals (key )
993+ || Registries .CONFIGURED_CARVER .equals (key )
994+ || Registries .PLACED_FEATURE .equals (key )
995+ || Registries .CONFIGURED_FEATURE .equals (key );
996+ }
997+ ),
930998 new RegistryLoadAttempt (
931999 "unfiltered" ,
9321000 resourceManager ,
@@ -986,6 +1054,19 @@ private static List<RegistryDataLoader.RegistryData<?>> filterRegistryData(
9861054 .toList ();
9871055 }
9881056
1057+ private static boolean isWorldgenResource (Identifier id ) {
1058+ if (id == null ) return false ;
1059+ String path = id .getPath ();
1060+ if (path == null ) return false ;
1061+ return path .startsWith ("worldgen/noise_settings" )
1062+ || path .startsWith ("worldgen/density_function" )
1063+ || path .startsWith ("worldgen/world_preset" )
1064+ || path .startsWith ("worldgen/configured_carver" )
1065+ || path .startsWith ("worldgen/placed_feature" )
1066+ || path .startsWith ("worldgen/configured_feature" )
1067+ || path .startsWith ("worldgen/configured_carver" );
1068+ }
1069+
9891070 private static boolean isEnchantmentResource (Identifier id ) {
9901071 if (id == null ) {
9911072 return false ;
0 commit comments