diff --git a/pom.xml b/pom.xml index 269f5b0..ea38ff5 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ -LOCAL - 2.4.0 + 2.5.0 BentoBoxWorld_Boxed bentobox-world diff --git a/src/main/java/world/bentobox/boxed/Boxed.java b/src/main/java/world/bentobox/boxed/Boxed.java index 71be0ca..8255fb5 100644 --- a/src/main/java/world/bentobox/boxed/Boxed.java +++ b/src/main/java/world/bentobox/boxed/Boxed.java @@ -58,15 +58,12 @@ public class Boxed extends GameModeAddon { private static final String SEED = "seed"; private static final String NETHER = "_nether"; private static final String THE_END = "_the_end"; - private static final String BASE = "_base"; // Settings private Settings settings; private AbstractBoxedChunkGenerator worldGen; - private AbstractBoxedChunkGenerator seedBaseGen; private BoxedSeedChunkGenerator seedGen; private AbstractBoxedChunkGenerator netherGen; - private AbstractBoxedChunkGenerator netherSeedBaseGen; private BoxedSeedChunkGenerator netherSeedGen; @@ -75,7 +72,6 @@ public class Boxed extends GameModeAddon { private World seedWorld; private final Map generatorMap = new HashMap<>(); private final Map generatorMaps = new HashMap<>(); - //private World seedWorldEnd; private BiomeProvider boxedBiomeProvider; @Override @@ -111,22 +107,16 @@ public class Boxed extends GameModeAddon { this.worldGen = new BoxedChunkGenerator(this); generatorMaps.put(settings.getWorldName(), worldGen); - seedBaseGen = new BoxedSeedChunkGenerator(this, Environment.NORMAL); - generatorMaps.put(settings.getWorldName() + "/" + SEED + BASE, seedBaseGen); - seedGen = new BoxedSeedChunkGenerator(this, Environment.NORMAL, - new SeedBiomeGenerator(this, seedBaseGen)); + new SeedBiomeGenerator(this)); generatorMaps.put(settings.getWorldName() + "/" + SEED, seedGen); // Nether generators this.netherGen = new BoxedChunkGenerator(this); generatorMaps.put(settings.getWorldName() + NETHER, netherGen); - netherSeedBaseGen = new BoxedSeedChunkGenerator(this, Environment.NETHER); - generatorMaps.put(settings.getWorldName() + "/" + SEED + NETHER + BASE, netherSeedBaseGen); // + SEED + NETHER + BASE) - netherSeedGen = new BoxedSeedChunkGenerator(this, Environment.NETHER, - new NetherSeedBiomeGenerator(this, seedBaseGen)); + new NetherSeedBiomeGenerator(this)); generatorMaps.put(settings.getWorldName() + "/" + SEED + NETHER, netherSeedGen); return true; @@ -206,20 +196,6 @@ public class Boxed extends GameModeAddon { private void createNether(String worldName) { // Create vanilla seed nether world log("Creating Boxed Seed Nether world ..."); - World baseWorldNether = WorldCreator - .name(worldName + "/" + SEED + NETHER + BASE) - .generator(netherSeedBaseGen) - .environment(Environment.NETHER) - .seed(getSettings().getSeed()) - .createWorld(); - baseWorldNether.setDifficulty(Difficulty.PEACEFUL); - baseWorldNether.setSpawnLocation(settings.getSeedX(), 64, settings.getSeedZ()); - generatorMap.put(baseWorldNether, netherSeedBaseGen); - getPlugin().getIWM().addWorld(baseWorldNether, this); - copyChunks(baseWorldNether, netherSeedBaseGen); - // Create seed world - // This copies a base world with custom biomes - log("Creating Boxed Biomed Nether world ..."); World seedWorldNether = WorldCreator .name(worldName + "/" + SEED + NETHER) .generator(netherSeedGen) @@ -242,21 +218,6 @@ public class Boxed extends GameModeAddon { private void createOverWorld(String worldName) { // Create vanilla seed world log("Creating Boxed Seed world ..."); - // This creates a vanilla base world with biomes - World baseWorld = WorldCreator - .name(worldName + "/" + SEED + BASE) - .generator(seedBaseGen) - .environment(Environment.NORMAL) - .seed(getSettings().getSeed()) - .createWorld(); - baseWorld.setDifficulty(Difficulty.PEACEFUL); - baseWorld.setSpawnLocation(settings.getSeedX(), 64, settings.getSeedZ()); - generatorMap.put(baseWorld, seedBaseGen); - getPlugin().getIWM().addWorld(baseWorld, this); - copyChunks(baseWorld, seedBaseGen); - // Create seed world - // This copies a base world with custom biomes - log("Creating Boxed Biomed world ..."); seedWorld = WorldCreator .name(worldName + "/" + SEED) .generator(seedGen) diff --git a/src/main/java/world/bentobox/boxed/Settings.java b/src/main/java/world/bentobox/boxed/Settings.java index 81142d8..d665c00 100644 --- a/src/main/java/world/bentobox/boxed/Settings.java +++ b/src/main/java/world/bentobox/boxed/Settings.java @@ -131,7 +131,7 @@ public class Settings implements WorldSettings { @ConfigEntry(path = "world.max-areas") private int maxIslands = -1; - @ConfigComment("Area height - Lowest is 5.") + @ConfigComment("Area height") @ConfigComment("It is the y coordinate of the bedrock block in the blueprint.") @ConfigEntry(path = "world.area-height") private int islandHeight = 8; diff --git a/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java b/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java index 8efd5cb..ac10713 100644 --- a/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java +++ b/src/main/java/world/bentobox/boxed/generators/biomes/AbstractSeedBiomeProvider.java @@ -8,7 +8,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.SortedMap; import java.util.TreeMap; @@ -16,6 +15,7 @@ import org.bukkit.World.Environment; import org.bukkit.block.Biome; import org.bukkit.block.BlockFace; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.generator.BiomeParameterPoint; import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.WorldInfo; import org.bukkit.util.Vector; @@ -24,8 +24,6 @@ import org.eclipse.jdt.annotation.NonNull; import com.google.common.base.Enums; import world.bentobox.boxed.Boxed; -import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator; -import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator.ChunkStore; /** * Generates the biomes for the seed world. A seed world is the template for the chunks that @@ -36,7 +34,6 @@ import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator.ChunkS public abstract class AbstractSeedBiomeProvider extends BiomeProvider { private static final Map ENV_MAP; - private static final int DEPTH = 50; static { Map e = new EnumMap<>(Environment.class); @@ -46,22 +43,258 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { ENV_MAP = Collections.unmodifiableMap(e); } + /** + * Heights / ridges by erosion + */ + private enum Ridges { + VALLEYS(-1.0, -0.85), LOW(-0.85, -0.6), MID(-0.6, 0.2), HIGH(0.2, 0.7), PEAKS(0.7, 1.0); + + private double low; + private double high; + + Ridges(double low, double high) { + this.low = low; + this.high = high; + } + + public static Ridges getRidge(double erosion) { + for (Ridges r : Ridges.values()) { + if (erosion >= r.low && erosion < r.high) { + return r; + } + } + return MID; + } + + } + + /** + * Badland Biones by Humidity Zone + */ + private enum BadlandBiome { + HZONE0(0, Biome.BADLANDS, Biome.ERODED_BADLANDS), HZONE1(1, Biome.BADLANDS, Biome.ERODED_BADLANDS), + HZONE2(2, Biome.BADLANDS, Biome.BADLANDS), HZONE3(3, Biome.WOODED_BADLANDS, Biome.WOODED_BADLANDS), + HZONE4(4, Biome.WOODED_BADLANDS, Biome.WOODED_BADLANDS); + + private int humidityZone; + private Biome biome; + private Biome biome2; + + BadlandBiome(int h, Biome biome, Biome biome2) { + this.humidityZone = h; + this.biome = biome; + this.biome2 = biome2; + } + + public static Biome getBiome(int humidity, double weirdness) { + for (BadlandBiome mb : BadlandBiome.values()) { + if (mb.humidityZone == humidity) { + if (weirdness < 0) { + return mb.biome; + } else { + return mb.biome2; + } + } + } + throw new IllegalArgumentException("badlands biome h = " + humidity); + } + } + + /** + * Middle Biomes by temperature and humidity zones + */ + private enum MiddleBiome { + X00(0, 0, Biome.SNOWY_PLAINS, Biome.ICE_SPIKES), X01(0, 1, Biome.PLAINS, Biome.PLAINS), + X02(0, 2, Biome.FLOWER_FOREST, Biome.SUNFLOWER_PLAINS), x03(0, 3, Biome.SAVANNA, Biome.SAVANNA), + X04(0, 4, Biome.DESERT, Biome.DESERT), + + X10(1, 0, Biome.SNOWY_PLAINS, Biome.SNOWY_PLAINS), X11(1, 1, Biome.PLAINS, Biome.PLAINS), + X12(1, 2, Biome.PLAINS, Biome.PLAINS), X13(1, 3, Biome.SAVANNA, Biome.SAVANNA), + X14(1, 4, Biome.DESERT, Biome.DESERT), + + X20(2, 0, Biome.SNOWY_PLAINS, Biome.SNOWY_TAIGA), X21(2, 1, Biome.FOREST, Biome.FOREST), + X22(2, 2, Biome.FOREST, Biome.FOREST), X23(2, 3, Biome.FOREST, Biome.PLAINS), + X24(2, 4, Biome.DESERT, Biome.DESERT), + + X30(3, 0, Biome.SNOWY_TAIGA, Biome.SNOWY_TAIGA), X31(3, 1, Biome.TAIGA, Biome.TAIGA), + X32(3, 2, Biome.BIRCH_FOREST, Biome.OLD_GROWTH_BIRCH_FOREST), X33(3, 3, Biome.JUNGLE, Biome.SPARSE_JUNGLE), + X34(3, 4, Biome.DESERT, Biome.DESERT), + + X40(4, 0, Biome.TAIGA, Biome.TAIGA), X41(4, 1, Biome.OLD_GROWTH_SPRUCE_TAIGA, Biome.OLD_GROWTH_PINE_TAIGA), + X42(4, 2, Biome.DARK_FOREST, Biome.DARK_FOREST), X43(4, 3, Biome.JUNGLE, Biome.BAMBOO_JUNGLE), + X44(4, 4, Biome.DESERT, Biome.DESERT), + ; + + private int temperature; + private int humidity; + private Biome biome; + private Biome weirdBiome; // What the biome be if the weirdness is high enough + + MiddleBiome(int h, int t, Biome b, Biome weirdBiome) { + this.humidity = h; + this.temperature = t; + this.weirdBiome = weirdBiome; + this.biome = b; + } + + public static Biome getBiome(int humidity, int temperature, double weirdness) { + for (MiddleBiome mb : MiddleBiome.values()) { + if (mb.humidity == humidity && mb.temperature == temperature) { + if (weirdness < 0) { + return mb.biome; + } else { + return mb.weirdBiome; + } + } + } + throw new IllegalArgumentException("middle biome h = " + humidity + " t = " + temperature); + } + } + + /** + * Plateau biomes by temperature and humidity zones + */ + private enum PlateauBiome { + X00(0, 0, Biome.SNOWY_PLAINS, Biome.ICE_SPIKES), x01(0, 1, Biome.MEADOW, Biome.CHERRY_GROVE), + X02(0, 2, Biome.MEADOW, Biome.CHERRY_GROVE), x03(0, 3, Biome.SAVANNA_PLATEAU, Biome.SAVANNA_PLATEAU), + X04(0, 4, Biome.BADLANDS, Biome.ERODED_BADLANDS), + + X10(1, 0, Biome.SNOWY_PLAINS, Biome.SNOWY_PLAINS), x11(1, 1, Biome.MEADOW, Biome.MEADOW), + X12(1, 2, Biome.MEADOW, Biome.CHERRY_GROVE), x13(1, 3, Biome.SAVANNA_PLATEAU, Biome.SAVANNA_PLATEAU), + X14(1, 4, Biome.BADLANDS, Biome.ERODED_BADLANDS), + + X20(2, 0, Biome.SNOWY_PLAINS, Biome.SNOWY_TAIGA), x21(2, 1, Biome.FOREST, Biome.MEADOW), + X22(2, 2, Biome.MEADOW, Biome.BIRCH_FOREST), x23(2, 3, Biome.FOREST, Biome.FOREST), + X24(2, 4, Biome.BADLANDS, Biome.BADLANDS), + + X30(3, 0, Biome.SNOWY_TAIGA, Biome.SNOWY_TAIGA), x31(3, 1, Biome.TAIGA, Biome.MEADOW), + X32(3, 2, Biome.MEADOW, Biome.BIRCH_FOREST), x33(3, 3, Biome.FOREST, Biome.FOREST), + X34(3, 4, Biome.WOODED_BADLANDS, Biome.WOODED_BADLANDS), + + X40(4, 0, Biome.SNOWY_TAIGA, Biome.SNOWY_TAIGA), + X41(4, 1, Biome.OLD_GROWTH_SPRUCE_TAIGA, Biome.OLD_GROWTH_PINE_TAIGA), + X42(4, 2, Biome.DARK_FOREST, Biome.DARK_FOREST), x43(4, 3, Biome.JUNGLE, Biome.JUNGLE), + X44(4, 4, Biome.WOODED_BADLANDS, Biome.WOODED_BADLANDS),; + + private int temp; + private int humidity; + private Biome b; + private Biome weirdBiome; + + PlateauBiome(int humidity, int temp, Biome b, Biome weirdBiome) { + this.humidity = humidity; + this.temp = temp; + this.weirdBiome = weirdBiome; + this.b = b; + } + + public static Biome getBiome(int humidity, int temp, double weirdness) { + for (PlateauBiome mb : PlateauBiome.values()) { + if (mb.humidity == humidity && mb.temp == temp) { + if (weirdness < 0) { + return mb.b; + } else { + return mb.weirdBiome; + } + } + } + throw new IllegalArgumentException("plateau biome h = " + humidity + " t = " + temp); + } + } + + /** + * Shattered biomes by temperature and humidity + */ + private enum ShatteredBiome { + X00(0, 0, Biome.WINDSWEPT_GRAVELLY_HILLS, Biome.WINDSWEPT_GRAVELLY_HILLS), + X01(0, 1, Biome.WINDSWEPT_GRAVELLY_HILLS, Biome.WINDSWEPT_GRAVELLY_HILLS), + X02(0, 2, Biome.WINDSWEPT_HILLS, Biome.WINDSWEPT_HILLS), X03(0, 3, Biome.SAVANNA, Biome.SAVANNA), + X04(0, 4, Biome.DESERT, Biome.DESERT), + + X10(1, 0, Biome.WINDSWEPT_GRAVELLY_HILLS, Biome.WINDSWEPT_GRAVELLY_HILLS), + X11(1, 1, Biome.WINDSWEPT_GRAVELLY_HILLS, Biome.WINDSWEPT_GRAVELLY_HILLS), + X12(1, 2, Biome.WINDSWEPT_HILLS, Biome.WINDSWEPT_HILLS), + X13(1, 3, Biome.SAVANNA_PLATEAU, Biome.SAVANNA_PLATEAU), X14(1, 4, Biome.DESERT, Biome.DESERT), + + X20(2, 0, Biome.WINDSWEPT_HILLS, Biome.WINDSWEPT_HILLS), + X21(2, 1, Biome.WINDSWEPT_HILLS, Biome.WINDSWEPT_HILLS), + X22(2, 2, Biome.WINDSWEPT_HILLS, Biome.WINDSWEPT_HILLS), X23(2, 3, Biome.FOREST, Biome.FOREST), + X24(2, 4, Biome.DESERT, Biome.DESERT), + + X30(3, 0, Biome.WINDSWEPT_FOREST, Biome.WINDSWEPT_FOREST), + X31(3, 1, Biome.WINDSWEPT_FOREST, Biome.WINDSWEPT_FOREST), + X32(3, 2, Biome.WINDSWEPT_FOREST, Biome.WINDSWEPT_FOREST), X33(3, 3, Biome.JUNGLE, Biome.SPARSE_JUNGLE), + X34(3, 4, Biome.DESERT, Biome.DESERT), + + X40(4, 0, Biome.WINDSWEPT_FOREST, Biome.WINDSWEPT_FOREST), + X41(4, 1, Biome.WINDSWEPT_FOREST, Biome.WINDSWEPT_FOREST), + X42(4, 2, Biome.WINDSWEPT_FOREST, Biome.WINDSWEPT_FOREST), X43(4, 3, Biome.JUNGLE, Biome.BAMBOO_JUNGLE), + X44(4, 4, Biome.DESERT, Biome.DESERT),; + + private int temperature; + private int humidity; + private Biome biome; + private Biome weirdBiome; + + ShatteredBiome(int h, int t, Biome b, Biome weirdBiome) { + this.humidity = h; + this.temperature = t; + this.weirdBiome = weirdBiome; + this.biome = b; + } + + public static Biome getBiome(int h, int t, double we) { + for (ShatteredBiome mb : ShatteredBiome.values()) { + if (mb.humidity == h && mb.temperature == t) { + if (we < 0) { + return mb.biome; + } else { + return mb.weirdBiome; + } + } + } + throw new IllegalArgumentException("shattered biome h = " + h + " t = " + t); + } + } + + /** + * Continental location by continentalness + */ + private enum ContLoc { + MUSHROOM_FIELDS(-1.2, -1.05), + DEEP_OCEAN(-1.05, -0.455), + OCEAN(-0.455, -0.19), + COAST(-0.19, -0.11), + NEAR_INLAND(-0.11, 0.03), + MID_INLAND(0.03, 0.3), + FAR_INLAND(0.3, 10.0); + + private double min; + private double max; + + ContLoc(double min, double max) { + this.min = min; + this.max = max; + } + + public static ContLoc getCont(double continentalness) { + for (ContLoc c : ContLoc.values()) { + if (continentalness >= c.min && continentalness < c.max) { + return c; + } + } + throw new IllegalArgumentException("contloc out of spec value = " + continentalness); + } + } + private final Boxed addon; - private final Biome defaultBiome; - //private Map, Biome> biomeCache = new HashMap<>(); - protected final int dist; - private final int spawnX; private final int spawnZ; protected final Map> quadrants; - private final AbstractBoxedChunkGenerator seedGen; - - protected AbstractSeedBiomeProvider(Boxed boxed, Environment env, Biome defaultBiome, AbstractBoxedChunkGenerator seedGen) { + protected AbstractSeedBiomeProvider(Boxed boxed, Environment env) { this.addon = boxed; - this.defaultBiome = defaultBiome; - this.seedGen = seedGen; // These fields are used to determine the biomes around the spawn point this.dist = addon.getSettings().getIslandDistance(); if (env.equals(Environment.NORMAL)) { @@ -95,12 +328,14 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { return en == null ? null : en.getValue(); } - /** - * x, y, and z are block coordinates - */ + @Override + public Biome getBiome(WorldInfo worldInfo, int x, int y, int z, BiomeParameterPoint biomeParameterPoint) { + return this.getMappedBiome(worldInfo, x, y, z, biomeParameterPoint); + } + @Override public Biome getBiome(WorldInfo worldInfo, int x, int y, int z) { - return this.getMappedBiome(worldInfo, x, y, z); + throw new IllegalStateException("This method should never be called."); } /** @@ -112,24 +347,800 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { * @return Biome */ @NonNull - private Biome getVanillaBiome(WorldInfo worldInfo, int x, int y, int z) { - // Get the chunk coordinates - int chunkX = AbstractBoxedChunkGenerator.repeatCalc(x >> 4); - int chunkZ = AbstractBoxedChunkGenerator.repeatCalc(z >> 4); - // Get the stored snapshot - ChunkStore snapshot = this.seedGen.getChunk(chunkX, chunkZ); - if (snapshot == null) { - // This snapshot is not stored... - return defaultBiome; + private Biome getVanillaBiome(WorldInfo worldInfo, int x, int y, int z, BiomeParameterPoint bpb, Biome def) { + if (worldInfo.getEnvironment() == Environment.NORMAL) { + return getNormalBiome(bpb, def); } - // Get the in-chunk coordinates - int xx = Math.floorMod(x, 16); - int zz = Math.floorMod(z, 16); - //int yy = Math.max(Math.min(y * 4, worldInfo.getMaxHeight()), worldInfo.getMinHeight()); // To handle bug in Spigot + return getNetherBiome(bpb); - Biome b = snapshot.chunkBiomes().getOrDefault(new Vector(xx, y, zz), defaultBiome); + } - return Objects.requireNonNull(b); + private @NonNull Biome getNetherBiome(BiomeParameterPoint bpb) { + // Bring these values to 1 decimal place + double temp = Math.round(bpb.getTemperature() * 10.0) / 10.0; + double humidity = Math.round(bpb.getHumidity() * 10.0) / 10.0; + if (temp == -0.5D && humidity == 0.0D) { + return Biome.BASALT_DELTAS; + } else if (temp == 0.4D && humidity == 0.0D) { + return Biome.CRIMSON_FOREST; + } else if (temp == 0.0D && humidity == -0.5D) { + return Biome.SOUL_SAND_VALLEY; + } else if (temp == -0.5D && humidity == 0.5D) { + return Biome.WARPED_FOREST; + } + + return Biome.NETHER_WASTES; + } + + private @NonNull Biome getNormalBiome(BiomeParameterPoint bpb, Biome def) { + /* + * Caves + */ + double d = bpb.getDepth(); + if (d > 0.2 && d < 0.9) { + if (bpb.getHumidity() >= 0.4 && bpb.getHumidity() < 1.0) { + def = Biome.LUSH_CAVES; + } + if (bpb.getContinentalness() >= 0.8D && bpb.getContinentalness() <= 1.0D) { + def = Biome.DRIPSTONE_CAVES; + } + } + if (d >= 0.9) { // Vanilla has this as 1.1 + def = Biome.DEEP_DARK; + } + if (def != null) { + return def; + } + + /* + * Continentalness (also known as continents) is used to decide between ocean/beach/land biomes. + */ + int temp = getTemp(bpb.getTemperature()); + int humidity = getHumidity(bpb.getHumidity()); + int erosion = getErosion(bpb.getErosion()); + double we = bpb.getWeirdness(); + + return switch (ContLoc.getCont(bpb.getContinentalness())) { + case COAST -> coastBiome(humidity, temp, erosion, we); + case DEEP_OCEAN -> deepOceanBiome(temp); + case FAR_INLAND -> farInlandBiome(humidity, temp, erosion, we); + case MID_INLAND -> midInlandBiome(humidity, temp, erosion, we); + case MUSHROOM_FIELDS -> Biome.MUSHROOM_FIELDS; + case NEAR_INLAND -> nearInlandBiome(humidity, temp, erosion, we); + case OCEAN -> oceanBiome(temp); + default -> farInlandBiome(humidity, temp, erosion, we); + }; + } + + /** + * Erosion values are divided into 7 levels. The corresponding ranges from level 0 to level 6 are: + * -1.0~-0.78, -0.78~-0.375, -0.375~-0.2225, -0.2225~0.05, 0.05~0.45, 0.45~0.55, 0.55~1.0. + * + * @param erosion The erosion value + * @return The erosion level (0-6) + */ + private int getErosion(double erosion) { + if (erosion < -0.78) { + return 0; + } else if (erosion < -0.375) { + return 1; + } else if (erosion < -0.2225) { + return 2; + } else if (erosion < 0.05) { + return 3; + } else if (erosion < 0.45) { + return 4; + } else if (erosion < 0.55) { + return 5; + } else { + return 6; + } + } + + /** + * Humidity values are also divided into 5 levels. The corresponding ranges from level 0 to level 4 are: + * -1.0~-0.35, -0.35~-0.1, -0.1~0.1, 0.1~0.3, 0.3~1.0. + * + * @param humidity The humidity value + * @return The humidity level (0-4) + */ + private int getHumidity(double humidity) { + if (humidity < -0.35) { + return 0; + } else if (humidity < -0.1) { + return 1; + } else if (humidity < 0.1) { + return 2; + } else if (humidity < 0.3) { + return 3; + } else { + return 4; + } + } + + /** + * Temperature is a noise parameter used only in biome generation and does not affect terrain generation. + * Temperature values are divided into 5 levels. The corresponding ranges from level 0 to level 4 are: + * -1.0~-0.45, -0.45~-0.15, -0.15~0.2, 0.2~0.55, 0.55~1.0. + * + * @param temp The temperature value + * @return The temperature level (0-4) + */ + private int getTemp(double temp) { + if (temp < -0.45) { + return 0; + } else if (temp < -0.15) { + return 1; + } else if (temp < 0.2) { + return 2; + } else if (temp < 0.55) { + return 3; + } else { + return 4; + } + } + + + private @NonNull Biome oceanBiome(int temp) { + return switch (temp) { + case 0 -> Biome.FROZEN_OCEAN; + case 1 -> Biome.COLD_OCEAN; + case 2 -> Biome.OCEAN; + case 3 -> Biome.LUKEWARM_OCEAN; + case 4 -> Biome.WARM_OCEAN; + default -> Biome.OCEAN; + }; + } + + private @NonNull Biome deepOceanBiome(int temp) { + return switch (temp) { + case 0 -> Biome.DEEP_FROZEN_OCEAN; + case 1 -> Biome.DEEP_COLD_OCEAN; + case 2 -> Biome.DEEP_OCEAN; + case 3 -> Biome.DEEP_LUKEWARM_OCEAN; + case 4 -> Biome.WARM_OCEAN; + default -> Biome.DEEP_OCEAN; + }; + } + + private @NonNull Biome farInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + return switch (Ridges.getRidge(convertToY(weirdness))) { + case HIGH -> getFarInlandHighBiome(humidity, temperature, erosion, weirdness); + case LOW -> getFarInlandLowBiome(humidity, temperature, erosion, weirdness); + case MID -> getFarInlandMidBiome(humidity, temperature, erosion, weirdness); + case PEAKS -> getFarInlandPeaksBiome(humidity, temperature, erosion, weirdness); + default -> getFarInlandValleysBiome(humidity, temperature, erosion, weirdness); + }; + } + + private @NonNull Biome getFarInlandValleysBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion >= 0 && erosion < 6) { + if (temperature > 0D) { + return Biome.RIVER; + } else { + return Biome.FROZEN_RIVER; + } + } + // e == 6 + if (temperature == 0) { + return Biome.FROZEN_RIVER; + } + if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getValleysNearInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + return getFarInlandValleysBiome(humidity, temperature, erosion, weirdness); + } + + private @NonNull Biome getFarInlandPeaksBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature >= 0 && temperature <= 2) { + if (weirdness < 0) { + return Biome.JAGGED_PEAKS; + } else { + return Biome.FROZEN_PEAKS; + } + } else if (temperature == 3) { + return Biome.STONY_PEAKS; + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } else if (temperature == 0 && humidity > 1) { + return Biome.GROVE; + } else if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion <= 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Shattered biomes + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + // middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome getFarInlandMidBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature < 3 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature < 3 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature == 0 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 2) { + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 3) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1) || humidity == 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + if (temperature == 0) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getFarInlandLowBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion >= 0 && erosion < 2) { + if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion < 5) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + if (temperature == 0) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getFarInlandHighBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature < 3 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature < 3 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature == 0 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + if (temperature > 0 && temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 2 || erosion == 3 || erosion == 4) { + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 4 || erosion == 6) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome nearInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + return switch (Ridges.getRidge(convertToY(weirdness))) { + case HIGH -> getHighNearInlandBiome(humidity, temperature, erosion, weirdness); + case LOW -> getLowNearInlandBiome(humidity, temperature, erosion, weirdness); + case MID -> getMidNearInlandBiome(humidity, temperature, erosion, weirdness); + case PEAKS -> getPeaksNearInlandBiome(humidity, temperature, erosion, weirdness); + default -> getValleysNearInlandBiome(humidity, temperature, erosion, weirdness); + }; + } + + private @NonNull Biome getPeaksNearInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature >= 0 && temperature <= 2) { + if (weirdness < 0) { + return Biome.JAGGED_PEAKS; + } else { + return Biome.FROZEN_PEAKS; + } + } else if (temperature == 3) { + return Biome.STONY_PEAKS; + } + return BadlandBiome.getBiome(humidity, weirdness); + + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } else if (temperature == 0 && humidity > 1) { + return Biome.GROVE; + } else if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion <= 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Shattered biomes + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + // middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome getMidNearInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature < 3 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature < 3 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature == 0 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + if (temperature > 0 && temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion <= 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1) || humidity == 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + if (temperature == 0) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getLowNearInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion >= 0 && erosion < 2) { + if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion < 5) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + if (temperature == 0) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getHighNearInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature < 3 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature < 3 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature == 0 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + if (temperature > 0 && temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion <= 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1) || humidity == 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome midInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + return switch (Ridges.getRidge(convertToY(weirdness))) { + case HIGH -> getHighMidInlandBiome(humidity, temperature, erosion, weirdness); + case LOW -> getLowMidInlandBiome(humidity, temperature, erosion, weirdness); + case MID -> getMidMidInlandBiome(humidity, temperature, erosion, weirdness); + case PEAKS -> getPeaksMidInlandBiome(humidity, temperature, erosion, weirdness); + default -> getValleysMidInlandBiome(humidity, temperature, erosion, weirdness); + }; + } + + private @NonNull Biome getValleysMidInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0 || erosion == 1) { + if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else { + return BadlandBiome.getBiome(humidity, weirdness); + } + } + if (erosion >= 2 && erosion <= 5) { + if (temperature == 0) { + return Biome.FROZEN_RIVER; + } else { + return Biome.RIVER; + } + } + if (temperature == 0) { + return Biome.FROZEN_RIVER; + } + if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getPeaksMidInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0 || erosion == 1) { + if (temperature >= 0 && temperature <= 2) { + if (weirdness < 0) { + return Biome.JAGGED_PEAKS; + } else { + return Biome.FROZEN_PEAKS; + } + } else if (temperature == 3) { + return Biome.STONY_PEAKS; + } + return BadlandBiome.getBiome(humidity, weirdness); + + } else if (erosion == 2) { + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 3) { + if (temperature < 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 4 || erosion == 6) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome getMidMidInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature < 3 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature < 3 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature == 0 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + if (temperature > 0 && temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 2 || erosion == 3) { + if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + if (temperature == 0) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getLowMidInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0 || erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } else if (temperature == 0 && humidity > 1) { + return Biome.GROVE; + } else if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } + if (erosion == 2 || erosion == 3) { + if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } + // e == 6 + if (temperature == 0) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (temperature == 1 || temperature == 2) { + return Biome.SWAMP; + } + return Biome.MANGROVE_SWAMP; + } + + private @NonNull Biome getHighMidInlandBiome(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature < 3 && weirdness < 0D) { + return Biome.JAGGED_PEAKS; + } + if (temperature < 3 && weirdness > 0.0D) { + return Biome.FROZEN_PEAKS; + } + if (temperature == 3) { + return Biome.STONY_PEAKS; + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 1) { + if (temperature < 3 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } + if (temperature < 3 && (humidity == 2 || humidity == 3 || humidity == 4)) { + return Biome.GROVE; + } + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 2) { + return PlateauBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 3) { + if (temperature < 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion == 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome coastBiome(int humidity, int temperature, int erosion, double weirdness) { + return switch (Ridges.getRidge(convertToY(weirdness))) { + case HIGH -> getHighCoastBionme(humidity, temperature, erosion, weirdness); + case LOW -> getLowCoastBionme(humidity, temperature, erosion, weirdness); + case MID -> getMidCoastBionme(humidity, temperature, erosion, weirdness); + case PEAKS -> getPeaksCoastBionme(humidity, temperature, erosion, weirdness); + default -> getValleysCoastBionme(humidity, temperature, erosion, weirdness); + }; + } + + private @NonNull Biome getValleysCoastBionme(int humidity, int temperature, int erosion, double weirdness) { + if (temperature > 0D) { + return Biome.RIVER; + } + return Biome.FROZEN_RIVER; + } + + private @NonNull Biome getPeaksCoastBionme(int humidity, int temperature, int erosion, double weirdness) { + if (erosion == 0) { + if (temperature >= 0 && temperature <= 2) { + if (weirdness < 0) { + return Biome.JAGGED_PEAKS; + } else { + return Biome.FROZEN_PEAKS; + } + } else if (temperature == 3) { + return Biome.STONY_PEAKS; + } + return BadlandBiome.getBiome(humidity, weirdness); + + } else if (erosion == 1) { + if (temperature == 0 && (humidity == 0 || humidity == 1)) { + return Biome.SNOWY_SLOPES; + } else if (temperature == 0 && humidity > 1) { + return Biome.GROVE; + } else if (temperature < 4) { + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + return BadlandBiome.getBiome(humidity, weirdness); + } else if (erosion >= 2 && erosion <= 4) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Shattered biomes + return ShatteredBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + // middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + + private @NonNull Biome getMidCoastBionme(int humidity, int temperature, int erosion, double weirdness) { + if (erosion > 0 && erosion < 3) { + return Biome.STONY_SHORE; + } else if (erosion == 3) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 4) { + if (weirdness < 0) { + // Beach Biomes + return getBeachBiome(temperature); + } else { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + } else if (erosion == 5) { + if (weirdness < 0) { + // Beach Biomes + return getBeachBiome(temperature); + } + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + + } else if (erosion == 6) { + if (weirdness < 0D) { + // Beach Biomes + return getBeachBiome(temperature); + } else { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + } + // Else Beach biomes + return getBeachBiome(temperature); + } + + private @NonNull Biome getLowCoastBionme(int humidity, int temperature, int erosion, double weirdness) { + if (erosion >= 0 && erosion < 3) { + return Biome.STONY_SHORE; + } else if (erosion >= 3 && erosion < 5) { + // Beach Biomes + return getBeachBiome(temperature); + } else if (erosion == 5) { + if (weirdness < 0) { + // Beach Biomes + return getBeachBiome(temperature); + } + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + // Else Beach biomes + return getBeachBiome(temperature); + } + + private @NonNull Biome getHighCoastBionme(int humidity, int temperature, int erosion, double weirdness) { + if (erosion >= 0 && erosion < 5) { + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } else if (erosion == 5) { + if (weirdness < 0 && (temperature == 0 || temperature == 1 || humidity == 4)) { + // Middle biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + if (weirdness > 0 && (temperature > 2 && temperature <= 4 && humidity >= 0 && humidity <= 4)) { + return Biome.WINDSWEPT_SAVANNA; + } + } + // Middle Biomes + return MiddleBiome.getBiome(humidity, temperature, weirdness); + } + + Biome getBeachBiome(int t) { + return switch (t) { + case 0 -> Biome.SNOWY_BEACH; + case 4 -> Biome.DESERT; + default -> Biome.BEACH; + }; + } + + public static double convertToY(double x) { + x = Math.max(-1, Math.min(1, x)); // Clamp value + if (x >= -1 && x < -0.5) { + return 2 * x + 1; + } else if (x >= -0.5 && x < 0) { + return -2 * x; + } else if (x >= 0 && x < 0.5) { + return 2 * x; + } else if (x >= 0.5 && x <= 1) { + return -2 * x + 1; + } else { + throw new IllegalArgumentException("Invalid x value. x must be in the range [-1, 1]. Value = " + x); + } } /** @@ -138,32 +1149,21 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { * @param x - block coord * @param y - block coord * @param z - block coord + * @param biomeParameterPoint * @return Biome */ - private Biome getMappedBiome(WorldInfo worldInfo, int x, int y, int z) { - - // Custom biomes are not 3D yet - if (y < DEPTH) { - Biome result = getVanillaBiome(worldInfo, x, y, z); - return Objects.requireNonNull(result); - } - + private Biome getMappedBiome(WorldInfo worldInfo, int x, int y, int z, BiomeParameterPoint biomeParameterPoint) { /* * Biomes go around the island centers * */ - // Try to get the cached value - //Biome result = biomeCache.get((new Pair(x,z))); - //if (result != null) { - //return result; - //} Vector s = new Vector(x, 0, z); - Vector l = new Vector(spawnX,0,spawnZ); + Vector l = new Vector(spawnX, 0, spawnZ); double dis = l.distance(s); if (dis > dist * 2) { // Only customize biomes around the spawn location - return getVanillaBiome(worldInfo, x, y, z); + return getVanillaBiome(worldInfo, x, y, z, biomeParameterPoint, null); } // Provide custom biomes Biome result; @@ -180,11 +1180,15 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { } if (result == null || result.equals(Biome.CUSTOM)) { - result = getVanillaBiome(worldInfo, x, y, z); + result = getVanillaBiome(worldInfo, x, y, z, biomeParameterPoint, null); } - // Cache good result - //biomeCache.put(new Pair(x,z), result); + + // Caves + if (biomeParameterPoint.getDepth() > 0.2) { + result = getVanillaBiome(worldInfo, x, y, z, biomeParameterPoint, null); + } + return result; } @@ -192,7 +1196,7 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { @Override public List getBiomes(WorldInfo worldInfo) { // Return all of them for now! - return Arrays.stream(Biome.values()).filter(b -> !b.equals(Biome.CUSTOM)).filter(b -> !b.equals(Enums.getIfPresent(Biome.class, "CHERRY_GROVE").orNull())).toList(); + return Arrays.stream(Biome.values()).filter(b -> !b.equals(Biome.CUSTOM)).toList(); } /** @@ -219,8 +1223,9 @@ public abstract class AbstractSeedBiomeProvider extends BiomeProvider { // A biome of null means that no alternative biome should be applied result.put(d, biome); } - } catch(Exception e) { - addon.logError(sector + ": " + split[0] + " does not seem to be a double. For integers add a .0 to the end"); + } catch (Exception e) { + addon.logError(sector + ": " + split[0] + + " does not seem to be a double. For integers add a .0 to the end"); } } else { addon.logError(ring + " must be in the format ratio:biome where ratio is a double."); diff --git a/src/main/java/world/bentobox/boxed/generators/biomes/NetherSeedBiomeGenerator.java b/src/main/java/world/bentobox/boxed/generators/biomes/NetherSeedBiomeGenerator.java index 1577636..5589fff 100644 --- a/src/main/java/world/bentobox/boxed/generators/biomes/NetherSeedBiomeGenerator.java +++ b/src/main/java/world/bentobox/boxed/generators/biomes/NetherSeedBiomeGenerator.java @@ -1,10 +1,8 @@ package world.bentobox.boxed.generators.biomes; import org.bukkit.World.Environment; -import org.bukkit.block.Biome; import world.bentobox.boxed.Boxed; -import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator; /** * Generator for the Nether seed world @@ -13,8 +11,8 @@ import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator; */ public class NetherSeedBiomeGenerator extends AbstractSeedBiomeProvider { - public NetherSeedBiomeGenerator(Boxed boxed, AbstractBoxedChunkGenerator seedGen) { - super(boxed, Environment.NETHER, Biome.BASALT_DELTAS, seedGen); + public NetherSeedBiomeGenerator(Boxed boxed) { + super(boxed, Environment.NETHER); } } \ No newline at end of file diff --git a/src/main/java/world/bentobox/boxed/generators/biomes/SeedBiomeGenerator.java b/src/main/java/world/bentobox/boxed/generators/biomes/SeedBiomeGenerator.java index a6d36ab..a094e25 100644 --- a/src/main/java/world/bentobox/boxed/generators/biomes/SeedBiomeGenerator.java +++ b/src/main/java/world/bentobox/boxed/generators/biomes/SeedBiomeGenerator.java @@ -1,10 +1,8 @@ package world.bentobox.boxed.generators.biomes; import org.bukkit.World.Environment; -import org.bukkit.block.Biome; import world.bentobox.boxed.Boxed; -import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator; /** * Generator for the seed world @@ -13,8 +11,7 @@ import world.bentobox.boxed.generators.chunks.AbstractBoxedChunkGenerator; */ public class SeedBiomeGenerator extends AbstractSeedBiomeProvider { - public SeedBiomeGenerator(Boxed boxed, AbstractBoxedChunkGenerator seedGen) { - super(boxed, Environment.NORMAL, Biome.PLAINS, seedGen); + public SeedBiomeGenerator(Boxed boxed) { + super(boxed, Environment.NORMAL); } - } \ No newline at end of file diff --git a/src/main/java/world/bentobox/boxed/generators/chunks/AbstractBoxedChunkGenerator.java b/src/main/java/world/bentobox/boxed/generators/chunks/AbstractBoxedChunkGenerator.java index f668666..421ee44 100644 --- a/src/main/java/world/bentobox/boxed/generators/chunks/AbstractBoxedChunkGenerator.java +++ b/src/main/java/world/bentobox/boxed/generators/chunks/AbstractBoxedChunkGenerator.java @@ -38,6 +38,7 @@ public abstract class AbstractBoxedChunkGenerator extends ChunkGenerator { public AbstractBoxedChunkGenerator(Boxed addon) { this.addon = addon; size = (int)(addon.getSettings().getIslandDistance() / 16D); // Size is chunks + } /**