2016-06-22 23:49:47 -04:00
/*
2022-04-14 03:42:00 +00:00
* Copyright (c) Forge Development LLC and contributors
2022-02-28 13:41:23 -08:00
* SPDX-License-Identifier: LGPL-2.1-only
2016-06-22 23:49:47 -04:00
*/
2020-08-25 03:11:28 +02:00
2013-04-04 17:55:35 -07:00
package net.minecraftforge.common ;
import java.util.* ;
2022-04-14 11:13:14 -07:00
import java.util.concurrent.ConcurrentHashMap ;
2017-06-27 14:04:51 -07:00
import java.util.stream.Collectors ;
2020-10-15 12:43:18 -07:00
import java.util.stream.StreamSupport ;
2013-09-05 10:08:02 -04:00
2016-12-01 00:48:44 +01:00
import javax.annotation.Nonnull ;
2018-09-11 18:25:25 -07:00
import javax.annotation.Nullable ;
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
2016-04-09 18:03:46 -05:00
2021-07-17 00:08:49 -05:00
import net.minecraft.world.level.biome.Biomes ;
import net.minecraft.resources.ResourceKey ;
import net.minecraft.core.Registry ;
2013-04-04 17:55:35 -07:00
import static net.minecraftforge.common.BiomeDictionary.Type.* ;
2018-09-06 04:39:01 -07:00
import net.minecraftforge.registries.ForgeRegistries ;
2016-12-01 00:48:44 +01:00
import com.google.common.collect.ImmutableList ;
2013-04-04 17:55:35 -07:00
2021-07-17 00:08:49 -05:00
import net.minecraft.world.level.biome.Biome ;
2013-04-04 17:55:35 -07:00
public class BiomeDictionary
{
2017-06-27 14:04:51 -07:00
private static final boolean DEBUG = false ;
2018-09-11 18:25:25 -07:00
private static final Logger LOGGER = LogManager . getLogger ();
2017-06-27 14:04:51 -07:00
2016-12-01 00:48:44 +01:00
public static final class Type
2013-04-04 17:55:35 -07:00
{
2022-04-14 11:13:14 -07:00
private static final Map < String , Type > byName = new ConcurrentHashMap <> ();
2018-04-01 03:03:27 -05:00
private static Collection < Type > allTypes = Collections . unmodifiableCollection ( byName . values ());
2016-12-01 00:48:44 +01:00
2020-10-15 12:43:18 -07:00
/*Temperature-based tags. Specifying neither implies a biome is temperate*/
2022-04-14 11:13:14 -07:00
public static final Type HOT = getType ( "HOT" );
public static final Type COLD = getType ( "COLD" );
2016-12-01 00:48:44 +01:00
2020-10-15 12:43:18 -07:00
//Tags specifying the amount of vegetation a biome has. Specifying neither implies a biome to have moderate amounts*/
2022-04-14 11:13:14 -07:00
public static final Type SPARSE = getType ( "SPARSE" );
public static final Type DENSE = getType ( "DENSE" );
2016-12-01 00:48:44 +01:00
2020-10-15 12:43:18 -07:00
//Tags specifying how moist a biome is. Specifying neither implies the biome as having moderate humidity*/
2022-04-14 11:13:14 -07:00
public static final Type WET = getType ( "WET" );
public static final Type DRY = getType ( "DRY" );
2016-12-01 00:48:44 +01:00
2014-07-01 12:46:00 +10:00
/*Tree-based tags, SAVANNA refers to dry, desert-like trees (Such as Acacia), CONIFEROUS refers to snowy trees (Such as Spruce) and JUNGLE refers to jungle trees.
2020-10-15 12:43:18 -07:00
* Specifying no tag implies a biome has temperate trees (Such as Oak)*/
2022-04-14 11:13:14 -07:00
public static final Type SAVANNA = getType ( "SAVANNA" );
public static final Type CONIFEROUS = getType ( "CONIFEROUS" );
public static final Type JUNGLE = getType ( "JUNGLE" );
2014-07-07 21:29:37 -07:00
2020-10-15 12:43:18 -07:00
/*Tags specifying the nature of a biome*/
2022-04-14 11:13:14 -07:00
public static final Type SPOOKY = getType ( "SPOOKY" );
public static final Type DEAD = getType ( "DEAD" );
public static final Type LUSH = getType ( "LUSH" );
public static final Type MUSHROOM = getType ( "MUSHROOM" );
public static final Type MAGICAL = getType ( "MAGICAL" );
public static final Type RARE = getType ( "RARE" );
public static final Type PLATEAU = getType ( "PLATEAU" );
public static final Type MODIFIED = getType ( "MODIFIED" );
public static final Type OCEAN = getType ( "OCEAN" );
public static final Type RIVER = getType ( "RIVER" );
2016-12-01 00:48:44 +01:00
/**
* A general tag for all water-based biomes. Shown as present if OCEAN or RIVER are.
2020-10-15 12:43:18 -07:00
**/
2022-04-14 11:13:14 -07:00
public static final Type WATER = getType ( "WATER" , OCEAN , RIVER );
2014-07-07 21:29:37 -07:00
2020-10-15 12:43:18 -07:00
/*Generic types which a biome can be*/
2022-04-14 11:13:14 -07:00
public static final Type MESA = getType ( "MESA" );
public static final Type FOREST = getType ( "FOREST" );
public static final Type PLAINS = getType ( "PLAINS" );
public static final Type HILLS = getType ( "HILLS" );
public static final Type SWAMP = getType ( "SWAMP" );
public static final Type SANDY = getType ( "SANDY" );
public static final Type SNOWY = getType ( "SNOWY" );
public static final Type WASTELAND = getType ( "WASTELAND" );
public static final Type BEACH = getType ( "BEACH" );
public static final Type VOID = getType ( "VOID" );
public static final Type UNDERGROUND = getType ( "UNDERGROUND" );
2022-01-20 21:21:45 +01:00
/*Mountain related tags*/
2022-04-14 11:13:14 -07:00
public static final Type PEAK = getType ( "PEAK" );
public static final Type SLOPE = getType ( "SLOPE" );
public static final Type MOUNTAIN = getType ( "MOUNTAIN" , PEAK , SLOPE );
2016-12-01 00:48:44 +01:00
2020-10-15 12:43:18 -07:00
/*Tags specifying the dimension a biome generates in. Specifying none implies a biome that generates in a modded dimension*/
2022-04-14 11:13:14 -07:00
public static final Type OVERWORLD = getType ( "OVERWORLD" );
public static final Type NETHER = getType ( "NETHER" );
public static final Type END = getType ( "END" );
2019-11-01 12:26:08 -06:00
2016-12-01 00:48:44 +01:00
private final String name ;
private final List < Type > subTypes ;
2022-04-14 11:13:14 -07:00
private final Set < ResourceKey < Biome >> biomes = ConcurrentHashMap . newKeySet ();
2021-07-17 00:08:49 -05:00
private final Set < ResourceKey < Biome >> biomesUn = Collections . unmodifiableSet ( biomes );
2016-12-01 00:48:44 +01:00
private Type ( String name , Type ... subTypes )
{
this . name = name ;
this . subTypes = ImmutableList . copyOf ( subTypes );
}
/**
* Gets the name for this type.
2020-10-15 12:43:18 -07:00
*/
2016-12-01 00:48:44 +01:00
public String getName ()
2014-07-01 12:46:00 +10:00
{
2016-12-01 00:48:44 +01:00
return name ;
2014-07-01 12:46:00 +10:00
}
2014-07-07 21:29:37 -07:00
2016-12-01 00:48:44 +01:00
public String toString ()
2014-07-01 12:46:00 +10:00
{
2016-12-01 00:48:44 +01:00
return name ;
2014-07-01 12:46:00 +10:00
}
2014-07-07 21:29:37 -07:00
/**
2016-12-01 00:48:44 +01:00
* Retrieves a Type instance by name,
2014-07-07 21:29:37 -07:00
* if one does not exist already it creates one.
2016-03-23 17:34:48 +03:00
* This can be used as intermediate measure for modders to
2016-12-01 00:48:44 +01:00
* add their own Biome types.
* <p>
* There are <i>no</i> naming conventions besides:
* <ul><li><b>Must</b> be all upper case (enforced by name.toUpper())</li>
* <li><b>No</b> Special characters. {Unenforced, just don't be a pain, if it becomes a issue I WILL
* make this RTE with no worry about backwards compatibility}</li></ul>
* <p>
2014-07-07 21:29:37 -07:00
* Note: For performance sake, the return value of this function SHOULD be cached.
* Two calls with the same name SHOULD return the same value.
*
* @param name The name of this Type
* @return An instance of Type for this name.
2020-10-15 12:43:18 -07:00
*/
2022-04-14 11:13:14 -07:00
public synchronized static Type getType ( String name , Type ... subTypes )
2014-07-07 21:29:37 -07:00
{
2022-04-14 11:13:14 -07:00
return byName . computeIfAbsent ( name . toUpperCase ( Locale . ENGLISH ), n -> new Type ( n , subTypes ));
2014-07-07 21:29:37 -07:00
}
2018-09-11 18:25:25 -07:00
2021-10-20 15:10:13 -04:00
/**
* Checks if a type instance exists for a given name. Does not have any side effects if a type does not already exist.
* This can be used for checking if a user-defined type is valid, for example, in a codec which accepts biome dictionary names.
* @param name The name.
* @return {@code true} if a type exists with this name.
*
* @see #getType(String, Type...) #getType for type naming conventions.
*/
public static boolean hasType ( String name )
{
2022-04-14 11:13:14 -07:00
return byName . containsKey ( name . toUpperCase ( Locale . ENGLISH ));
2021-10-20 15:10:13 -04:00
}
2018-04-01 03:03:27 -05:00
/**
* @return An unmodifiable collection of all current biome types.
2020-10-15 12:43:18 -07:00
*/
2018-04-01 03:03:27 -05:00
public static Collection < Type > getAll ()
{
return allTypes ;
}
2018-09-11 18:25:25 -07:00
@Nullable
2021-07-17 00:08:49 -05:00
public static Type fromVanilla ( Biome . BiomeCategory category )
2018-09-11 18:25:25 -07:00
{
2021-07-17 00:08:49 -05:00
if ( category == Biome . BiomeCategory . NONE )
2018-09-11 18:25:25 -07:00
return null ;
2021-07-17 00:08:49 -05:00
if ( category == Biome . BiomeCategory . THEEND )
2018-09-11 18:25:25 -07:00
return VOID ;
return getType ( category . name ());
}
2013-04-04 17:55:35 -07:00
}
2021-07-17 00:08:49 -05:00
private static final Map < ResourceKey < Biome > , BiomeInfo > biomeInfoMap = new HashMap <> ();
2013-04-04 17:55:35 -07:00
private static class BiomeInfo
{
2016-12-01 00:48:44 +01:00
private final Set < Type > types = new HashSet < Type > ();
private final Set < Type > typesUn = Collections . unmodifiableSet ( this . types );
2013-04-04 17:55:35 -07:00
}
2020-10-15 12:43:18 -07:00
public static void init () {}
2013-04-04 17:55:35 -07:00
static
{
registerVanillaBiomes ();
}
/**
2016-12-01 00:48:44 +01:00
* Adds the given types to the biome.
2014-07-07 21:29:37 -07:00
*
2020-10-15 12:43:18 -07:00
*/
2021-07-17 00:08:49 -05:00
public static void addTypes ( ResourceKey < Biome > biome , Type ... types )
2014-07-07 21:29:37 -07:00
{
2017-02-04 18:29:42 +01:00
Collection < Type > supertypes = listSupertypes ( types );
2017-06-27 14:04:51 -07:00
Collections . addAll ( supertypes , types );
2013-04-04 17:55:35 -07:00
2017-02-04 18:29:42 +01:00
for ( Type type : supertypes )
2016-12-01 00:48:44 +01:00
{
type . biomes . add ( biome );
2013-04-04 17:55:35 -07:00
}
2017-02-05 18:47:07 +01:00
BiomeInfo biomeInfo = getBiomeInfo ( biome );
Collections . addAll ( biomeInfo . types , types );
biomeInfo . types . addAll ( supertypes );
2013-04-04 17:55:35 -07:00
}
/**
2016-12-01 00:48:44 +01:00
* Gets the set of biomes that have the given type.
2014-07-07 21:29:37 -07:00
*
2020-10-15 12:43:18 -07:00
*/
2016-12-01 00:48:44 +01:00
@Nonnull
2021-07-17 00:08:49 -05:00
public static Set < ResourceKey < Biome >> getBiomes ( Type type )
2013-04-04 17:55:35 -07:00
{
2016-12-01 00:48:44 +01:00
return type . biomesUn ;
2013-04-04 17:55:35 -07:00
}
/**
2016-12-01 00:48:44 +01:00
* Gets the set of types that have been added to the given biome.
2014-07-07 21:29:37 -07:00
*
2020-10-15 12:43:18 -07:00
*/
2016-12-01 00:48:44 +01:00
@Nonnull
2021-07-17 00:08:49 -05:00
public static Set < Type > getTypes ( ResourceKey < Biome > biome )
2013-04-04 17:55:35 -07:00
{
2016-12-01 00:48:44 +01:00
return getBiomeInfo ( biome ). typesUn ;
2013-04-04 17:55:35 -07:00
}
/**
2016-12-01 00:48:44 +01:00
* Checks if the two given biomes have types in common.
2014-07-07 21:29:37 -07:00
*
2013-04-04 17:55:35 -07:00
* @return returns true if a common type is found, false otherwise
2020-10-15 12:43:18 -07:00
*/
2021-07-17 00:08:49 -05:00
public static boolean areSimilar ( ResourceKey < Biome > biomeA , ResourceKey < Biome > biomeB )
2013-04-04 17:55:35 -07:00
{
2020-10-15 12:43:18 -07:00
Set < Type > typesA = getTypes ( biomeA );
Set < Type > typesB = getTypes ( biomeB );
return typesA . stream (). anyMatch ( typesB :: contains );
2013-04-04 17:55:35 -07:00
}
/**
2016-12-01 00:48:44 +01:00
* Checks if the given type has been added to the given biome.
2014-07-07 21:29:37 -07:00
*
2020-10-15 12:43:18 -07:00
*/
2021-07-17 00:08:49 -05:00
public static boolean hasType ( ResourceKey < Biome > biome , Type type )
2014-07-07 21:29:37 -07:00
{
2016-12-01 00:48:44 +01:00
return getTypes ( biome ). contains ( type );
2013-04-04 17:55:35 -07:00
}
/**
2016-12-01 00:48:44 +01:00
* Checks if any type has been added to the given biome.
2014-07-07 21:29:37 -07:00
*
2020-10-15 12:43:18 -07:00
*/
2021-07-17 00:08:49 -05:00
public static boolean hasAnyType ( ResourceKey < Biome > biome )
2013-04-04 17:55:35 -07:00
{
2016-12-01 00:48:44 +01:00
return ! getBiomeInfo ( biome ). types . isEmpty ();
2013-04-04 17:55:35 -07:00
}
2014-07-07 21:29:37 -07:00
//Internal implementation
2021-07-17 00:08:49 -05:00
private static BiomeInfo getBiomeInfo ( ResourceKey < Biome > biome )
2013-04-04 17:55:35 -07:00
{
2020-10-15 12:43:18 -07:00
return biomeInfoMap . computeIfAbsent ( biome , k -> new BiomeInfo ());
2013-04-04 17:55:35 -07:00
}
2017-02-04 18:29:42 +01:00
private static Collection < Type > listSupertypes ( Type ... types )
2013-04-04 17:55:35 -07:00
{
2017-02-04 18:29:42 +01:00
Set < Type > supertypes = new HashSet < Type > ();
Deque < Type > next = new ArrayDeque < Type > ();
Collections . addAll ( next , types );
2014-07-07 21:29:37 -07:00
2017-02-04 18:29:42 +01:00
while ( ! next . isEmpty ())
2014-07-01 12:46:00 +10:00
{
2017-02-04 18:29:42 +01:00
Type type = next . remove ();
for ( Type sType : Type . byName . values ())
2016-12-01 00:48:44 +01:00
{
2017-06-27 14:04:51 -07:00
if ( sType . subTypes . contains ( type ) && supertypes . add ( sType ))
2017-02-04 18:29:42 +01:00
next . add ( sType );
2016-12-01 00:48:44 +01:00
}
2014-07-01 12:46:00 +10:00
}
2014-07-07 21:29:37 -07:00
2017-02-04 18:29:42 +01:00
return supertypes ;
2014-07-01 12:46:00 +10:00
}
2013-04-04 17:55:35 -07:00
private static void registerVanillaBiomes ()
{
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . OCEAN , OCEAN , OVERWORLD );
addTypes ( Biomes . PLAINS , PLAINS , OVERWORLD );
addTypes ( Biomes . DESERT , HOT , DRY , SANDY , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . WINDSWEPT_HILLS , HILLS , OVERWORLD );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . FOREST , FOREST , OVERWORLD );
addTypes ( Biomes . TAIGA , COLD , CONIFEROUS , FOREST , OVERWORLD );
addTypes ( Biomes . SWAMP , WET , SWAMP , OVERWORLD );
addTypes ( Biomes . RIVER , RIVER , OVERWORLD );
2020-10-29 01:11:57 +01:00
addTypes ( Biomes . NETHER_WASTES , HOT , DRY , NETHER );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . THE_END , COLD , DRY , END );
addTypes ( Biomes . FROZEN_OCEAN , COLD , OCEAN , SNOWY , OVERWORLD );
addTypes ( Biomes . FROZEN_RIVER , COLD , RIVER , SNOWY , OVERWORLD );
2021-12-02 00:43:00 +00:00
addTypes ( Biomes . SNOWY_PLAINS , COLD , SNOWY , WASTELAND , OVERWORLD );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . MUSHROOM_FIELDS , MUSHROOM , RARE , OVERWORLD );
addTypes ( Biomes . BEACH , BEACH , OVERWORLD );
addTypes ( Biomes . JUNGLE , HOT , WET , DENSE , JUNGLE , OVERWORLD );
2021-12-02 00:43:00 +00:00
addTypes ( Biomes . SPARSE_JUNGLE , HOT , WET , JUNGLE , FOREST , RARE , OVERWORLD );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . DEEP_OCEAN , OCEAN , OVERWORLD );
2021-12-02 00:43:00 +00:00
addTypes ( Biomes . STONY_SHORE , BEACH , OVERWORLD );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . SNOWY_BEACH , COLD , BEACH , SNOWY , OVERWORLD );
addTypes ( Biomes . BIRCH_FOREST , FOREST , OVERWORLD );
addTypes ( Biomes . DARK_FOREST , SPOOKY , DENSE , FOREST , OVERWORLD );
addTypes ( Biomes . SNOWY_TAIGA , COLD , CONIFEROUS , FOREST , SNOWY , OVERWORLD );
2021-12-02 00:43:00 +00:00
addTypes ( Biomes . OLD_GROWTH_PINE_TAIGA , COLD , CONIFEROUS , FOREST , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . WINDSWEPT_FOREST , HILLS , FOREST , SPARSE , OVERWORLD );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . SAVANNA , HOT , SAVANNA , PLAINS , SPARSE , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . SAVANNA_PLATEAU , HOT , SAVANNA , PLAINS , SPARSE , RARE , OVERWORLD , SLOPE , PLATEAU );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . BADLANDS , MESA , SANDY , DRY , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . WOODED_BADLANDS , MESA , SANDY , DRY , SPARSE , OVERWORLD , SLOPE , PLATEAU );
addTypes ( Biomes . MEADOW , PLAINS , PLATEAU , SLOPE , OVERWORLD );
addTypes ( Biomes . GROVE , COLD , CONIFEROUS , FOREST , SNOWY , SLOPE , OVERWORLD );
addTypes ( Biomes . SNOWY_SLOPES , COLD , SPARSE , SNOWY , SLOPE , OVERWORLD );
addTypes ( Biomes . JAGGED_PEAKS , COLD , SPARSE , SNOWY , PEAK , OVERWORLD );
addTypes ( Biomes . FROZEN_PEAKS , COLD , SPARSE , SNOWY , PEAK , OVERWORLD );
addTypes ( Biomes . STONY_PEAKS , HOT , PEAK , OVERWORLD );
2020-08-13 00:13:48 -07:00
addTypes ( Biomes . SMALL_END_ISLANDS , END );
addTypes ( Biomes . END_MIDLANDS , END );
addTypes ( Biomes . END_HIGHLANDS , END );
addTypes ( Biomes . END_BARRENS , END );
addTypes ( Biomes . WARM_OCEAN , OCEAN , HOT , OVERWORLD );
addTypes ( Biomes . LUKEWARM_OCEAN , OCEAN , OVERWORLD );
addTypes ( Biomes . COLD_OCEAN , OCEAN , COLD , OVERWORLD );
addTypes ( Biomes . DEEP_LUKEWARM_OCEAN , OCEAN , OVERWORLD );
addTypes ( Biomes . DEEP_COLD_OCEAN , OCEAN , COLD , OVERWORLD );
addTypes ( Biomes . DEEP_FROZEN_OCEAN , OCEAN , COLD , OVERWORLD );
addTypes ( Biomes . THE_VOID , VOID );
addTypes ( Biomes . SUNFLOWER_PLAINS , PLAINS , RARE , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . WINDSWEPT_GRAVELLY_HILLS , HILLS , SPARSE , RARE , OVERWORLD );
addTypes ( Biomes . FLOWER_FOREST , FOREST , RARE , OVERWORLD );
addTypes ( Biomes . ICE_SPIKES , COLD , SNOWY , RARE , OVERWORLD );
addTypes ( Biomes . OLD_GROWTH_BIRCH_FOREST , FOREST , DENSE , RARE , OVERWORLD );
2021-12-02 00:43:00 +00:00
addTypes ( Biomes . OLD_GROWTH_SPRUCE_TAIGA , DENSE , FOREST , RARE , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . WINDSWEPT_SAVANNA , HOT , DRY , SPARSE , SAVANNA , HILLS , RARE , OVERWORLD );
addTypes ( Biomes . ERODED_BADLANDS , MESA , HOT , DRY , SPARSE , RARE , OVERWORLD );
2020-10-15 12:43:18 -07:00
addTypes ( Biomes . BAMBOO_JUNGLE , HOT , WET , RARE , JUNGLE , OVERWORLD );
2022-01-20 21:21:45 +01:00
addTypes ( Biomes . LUSH_CAVES , UNDERGROUND , LUSH , WET , OVERWORLD );
addTypes ( Biomes . DRIPSTONE_CAVES , UNDERGROUND , SPARSE , OVERWORLD );
2020-10-29 01:11:57 +01:00
addTypes ( Biomes . SOUL_SAND_VALLEY , HOT , DRY , NETHER );
addTypes ( Biomes . CRIMSON_FOREST , HOT , DRY , NETHER , FOREST );
addTypes ( Biomes . WARPED_FOREST , HOT , DRY , NETHER , FOREST );
addTypes ( Biomes . BASALT_DELTAS , HOT , DRY , NETHER );
2017-06-27 14:04:51 -07:00
if ( DEBUG )
{
2018-09-11 18:25:25 -07:00
StringBuilder buf = new StringBuilder ();
buf . append ( "BiomeDictionary:\n" );
2022-04-14 11:13:14 -07:00
Type . getAll (). stream ()
. sorted (( l , r ) -> l . getName (). compareTo ( r . getName ()))
. forEach ( type ->
2020-10-15 12:43:18 -07:00
buf . append ( " " ). append ( type . name ). append ( ": " )
. append ( type . biomes . stream ()
2021-07-17 00:08:49 -05:00
. map ( ResourceKey :: location )
2020-10-15 12:43:18 -07:00
. sorted (( a , b ) -> a . compareNamespaced ( b ))
. map ( Object :: toString )
. collect ( Collectors . joining ( ", " ))
)
. append ( '\n' )
);
boolean missing = false ;
2021-07-17 00:08:49 -05:00
List < ResourceKey < Biome >> all = StreamSupport . stream ( ForgeRegistries . BIOMES . spliterator (), false )
. map ( b -> ResourceKey . create ( Registry . BIOME_REGISTRY , b . getRegistryName ()))
2020-10-15 12:43:18 -07:00
. sorted (). collect ( Collectors . toList ());
2021-07-17 00:08:49 -05:00
for ( ResourceKey < Biome > key : all ) {
2020-10-15 12:43:18 -07:00
if ( ! biomeInfoMap . containsKey ( key )) {
if ( ! missing ) {
buf . append ( "Missing:\n" );
missing = true ;
}
2021-03-09 13:37:23 -08:00
buf . append ( " " ). append ( key . location ()). append ( '\n' );
2020-10-15 12:43:18 -07:00
}
}
2018-09-11 18:25:25 -07:00
LOGGER . debug ( buf . toString ());
2017-06-27 14:04:51 -07:00
}
2013-04-04 17:55:35 -07:00
}
2013-04-19 14:08:53 +03:00
}