Added support for subbiomes

This commit is contained in:
Adubbz 2019-05-19 23:25:32 +10:00
parent 6c4a11b15e
commit 0ff8ae6c7c
3 changed files with 230 additions and 1 deletions

View File

@ -10,6 +10,8 @@ package biomesoplenty.common.world;
import biomesoplenty.common.world.layer.*;
import biomesoplenty.common.world.layer.traits.LazyAreaLayerContextBOP;
import com.google.common.collect.ImmutableList;
import net.minecraft.init.Biomes;
import net.minecraft.util.registry.IRegistry;
import net.minecraft.world.WorldType;
import net.minecraft.world.gen.IContextExtended;
import net.minecraft.world.gen.OverworldGenSettings;
@ -22,6 +24,17 @@ import java.util.function.LongFunction;
public class BOPLayerUtil
{
public static final int WARM_OCEAN = IRegistry.BIOME.getId(Biomes.WARM_OCEAN);
public static final int LUKEWARM_OCEAN = IRegistry.BIOME.getId(Biomes.LUKEWARM_OCEAN);
public static final int OCEAN = IRegistry.BIOME.getId(Biomes.OCEAN);
public static final int COLD_OCEAN = IRegistry.BIOME.getId(Biomes.COLD_OCEAN);
public static final int FROZEN_OCEAN = IRegistry.BIOME.getId(Biomes.FROZEN_OCEAN);
public static final int DEEP_WARM_OCEAN = IRegistry.BIOME.getId(Biomes.DEEP_WARM_OCEAN);
public static final int DEEP_LUKEWARM_OCEAN = IRegistry.BIOME.getId(Biomes.DEEP_LUKEWARM_OCEAN);
public static final int DEEP_OCEAN = IRegistry.BIOME.getId(Biomes.DEEP_OCEAN);
public static final int DEEP_COLD_OCEAN = IRegistry.BIOME.getId(Biomes.DEEP_COLD_OCEAN);
public static final int DEEP_FROZEN_OCEAN = IRegistry.BIOME.getId(Biomes.DEEP_FROZEN_OCEAN);
public static <T extends IArea, C extends IContextExtended<T>> IAreaFactory<T> createInitialLandAndSeaFactory(LongFunction<C> contextFactory)
{
// NOTE: Normally AddSnow, CoolWarm, HeatIce and Special GenLayers occur here, but we handle those ourselves
@ -124,7 +137,7 @@ public class BOPLayerUtil
// Allocate the biomes
IAreaFactory<T> climateFactory = createClimateFactory(contextFactory, new BOPWorldSettings());
IAreaFactory<T> biomesFactory = createBiomeFactory(landSeaFactory, climateFactory, contextFactory);
biomesFactory = GenLayerHills.INSTANCE.apply(contextFactory.apply(1000L), biomesFactory, riverAndSubBiomesInitFactory);
biomesFactory = GenLayerSubBiome.INSTANCE.apply(contextFactory.apply(1000L), biomesFactory, riverAndSubBiomesInitFactory);
// Develop the rivers branch
IAreaFactory<T> riversInitFactory = LayerUtil.repeat(1000L, GenLayerZoom.NORMAL, riverAndSubBiomesInitFactory, riverSize, contextFactory);
@ -167,4 +180,14 @@ public class BOPLayerUtil
GenLayer biomesLayer2 = new GenLayer(factoryList.get(2));
return new GenLayer[]{biomesLayer, voroniZoomBiomesLayer, biomesLayer2};
}
public static boolean isOcean(int biomeIn)
{
return biomeIn == WARM_OCEAN || biomeIn == LUKEWARM_OCEAN || biomeIn == OCEAN || biomeIn == COLD_OCEAN || biomeIn == FROZEN_OCEAN || biomeIn == DEEP_WARM_OCEAN || biomeIn == DEEP_LUKEWARM_OCEAN || biomeIn == DEEP_OCEAN || biomeIn == DEEP_COLD_OCEAN || biomeIn == DEEP_FROZEN_OCEAN;
}
public static boolean isShallowOcean(int biomeIn)
{
return biomeIn == WARM_OCEAN || biomeIn == LUKEWARM_OCEAN || biomeIn == OCEAN || biomeIn == COLD_OCEAN || biomeIn == FROZEN_OCEAN;
}
}

View File

@ -0,0 +1,175 @@
/*******************************************************************************
* Copyright 2014-2019, the Biomes O' Plenty Team
*
* This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License.
*
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
******************************************************************************/
package biomesoplenty.common.world.layer;
import biomesoplenty.api.enums.BOPClimates;
import biomesoplenty.common.world.BOPLayerUtil;
import biomesoplenty.init.ModBiomes;
import com.google.common.collect.Lists;
import net.minecraft.init.Biomes;
import net.minecraft.util.registry.IRegistry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.IContext;
import net.minecraft.world.gen.area.AreaDimension;
import net.minecraft.world.gen.area.IArea;
import net.minecraft.world.gen.layer.LayerUtil;
import net.minecraft.world.gen.layer.traits.IAreaTransformer2;
import net.minecraft.world.gen.layer.traits.IDimOffset1Transformer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Iterator;
import java.util.List;
public enum GenLayerSubBiome implements IAreaTransformer2, IDimOffset1Transformer
{
INSTANCE;
private static final int BIRCH_FOREST = IRegistry.BIOME.getId(Biomes.BIRCH_FOREST);
private static final int BIRCH_FOREST_HILLS = IRegistry.BIOME.getId(Biomes.BIRCH_FOREST_HILLS);
private static final int DESERT = IRegistry.BIOME.getId(Biomes.DESERT);
private static final int DESERT_HILLS = IRegistry.BIOME.getId(Biomes.DESERT_HILLS);
private static final int MOUNTAINS = IRegistry.BIOME.getId(Biomes.MOUNTAINS);
private static final int WOODED_MOUNTAINS = IRegistry.BIOME.getId(Biomes.WOODED_MOUNTAINS);
private static final int FOREST = IRegistry.BIOME.getId(Biomes.FOREST);
private static final int WOODED_HILLS = IRegistry.BIOME.getId(Biomes.WOODED_HILLS);
private static final int SNOWY_TUNDRA = IRegistry.BIOME.getId(Biomes.SNOWY_TUNDRA);
private static final int SNOWY_MOUNTAINS = IRegistry.BIOME.getId(Biomes.SNOWY_MOUNTAINS);
private static final int JUNGLE = IRegistry.BIOME.getId(Biomes.JUNGLE);
private static final int JUNGLE_HILLS = IRegistry.BIOME.getId(Biomes.JUNGLE_HILLS);
private static final int BADLANDS = IRegistry.BIOME.getId(Biomes.BADLANDS);
private static final int WOODED_BADLANDS_PLATEAU = IRegistry.BIOME.getId(Biomes.WOODED_BADLANDS_PLATEAU);
private static final int PLAINS = IRegistry.BIOME.getId(Biomes.PLAINS);
private static final int GIANT_TREE_TAIGA = IRegistry.BIOME.getId(Biomes.GIANT_TREE_TAIGA);
private static final int GIANT_TREE_TAIGA_HILLS = IRegistry.BIOME.getId(Biomes.GIANT_TREE_TAIGA_HILLS);
private static final int DARK_FOREST = IRegistry.BIOME.getId(Biomes.DARK_FOREST);
private static final int SAVANNA = IRegistry.BIOME.getId(Biomes.SAVANNA);
private static final int SAVANA_PLATEAU = IRegistry.BIOME.getId(Biomes.SAVANNA_PLATEAU);
private static final int TAIGA = IRegistry.BIOME.getId(Biomes.TAIGA);
private static final int SNOWY_TAIGA = IRegistry.BIOME.getId(Biomes.SNOWY_TAIGA);
private static final int SNOWY_TAIGA_HILLS = IRegistry.BIOME.getId(Biomes.SNOWY_TAIGA_HILLS);
private static final int TAIGA_HILLS = IRegistry.BIOME.getId(Biomes.TAIGA_HILLS);
@Override
public int apply(IContext context, AreaDimension dimension, IArea biomeArea, IArea riverAndSubBiomesInitArea, int x, int z)
{
int biomeId = biomeArea.getValue(x + 1, z + 1);
int initVal = riverAndSubBiomesInitArea.getValue(x + 1, z + 1);
int subBiomeType = (initVal - 2) % 29;
boolean tryRareHillsBiome = subBiomeType == 0;
boolean tryRareBiome = subBiomeType == 1;
Biome mutatedBiome;
if (!BOPLayerUtil.isShallowOcean(biomeId) && initVal >= 2 && tryRareBiome)
{
Biome biome = IRegistry.BIOME.get(biomeId);
if (biome == null || !biome.isMutation()) {
mutatedBiome = Biome.getMutationForBiome(biome);
return mutatedBiome == null ? biomeId : IRegistry.BIOME.getId(mutatedBiome);
}
}
if (context.random(3) == 0 || tryRareHillsBiome)
{
int mutatedBiomeId = this.getCommonSubBiomeId(context, biomeId);
if (mutatedBiomeId != biomeId)
return mutatedBiomeId;
mutatedBiomeId = this.getRareSubBiomeId(context, biomeId);
if (subBiomeType == 0 && mutatedBiomeId != biomeId)
{
mutatedBiome = Biome.getMutationForBiome(IRegistry.BIOME.get(mutatedBiomeId));
mutatedBiomeId = mutatedBiome == null ? biomeId : IRegistry.BIOME.getId(mutatedBiome);
}
if (mutatedBiomeId != biomeId)
{
int surroundingSimilarCount = 0;
if (LayerUtil.areBiomesSimilar(biomeArea.getValue(x + 1, z + 0), biomeId))
++surroundingSimilarCount;
if (LayerUtil.areBiomesSimilar(biomeArea.getValue(x + 2, z + 1), biomeId))
++surroundingSimilarCount;
if (LayerUtil.areBiomesSimilar(biomeArea.getValue(x + 0, z + 1), biomeId))
++surroundingSimilarCount;
if (LayerUtil.areBiomesSimilar(biomeArea.getValue(x + 1, z + 2), biomeId))
++surroundingSimilarCount;
if (surroundingSimilarCount >= 3)
return mutatedBiomeId;
}
}
return biomeId;
}
public int getCommonSubBiomeId(IContext context, int originalBiomeId)
{
float rarity = (float)context.random(100) / 100.0f;
List<BOPClimates.WeightedBiomeEntry> weightedBiomeEntryList = Lists.newArrayList();
int selectedBiomeId = originalBiomeId;
int totalWeight = 0;
// Find suitable candidates
for (ModBiomes.WeightedSubBiome entry : ModBiomes.subBiomes.get(originalBiomeId))
{
if (entry.rarity >= rarity)
{
weightedBiomeEntryList.add(new BOPClimates.WeightedBiomeEntry(entry.weight, entry.biome));
totalWeight += entry.weight;
}
}
if (totalWeight <= 0)
return selectedBiomeId;
int weight = context.random(totalWeight);
Iterator<BOPClimates.WeightedBiomeEntry> iterator = weightedBiomeEntryList.iterator();
BOPClimates.WeightedBiomeEntry item;
do
{
item = iterator.next();
weight -= item.weight;
}
while (weight >= 0);
selectedBiomeId = IRegistry.BIOME.getId(item.biome);
return selectedBiomeId;
}
public int getRareSubBiomeId(IContext context, int originalBiomeId)
{
int mutatedBiomeId = originalBiomeId;
if (originalBiomeId == DESERT) mutatedBiomeId = DESERT_HILLS;
else if (originalBiomeId == FOREST) mutatedBiomeId = WOODED_HILLS;
else if (originalBiomeId == BIRCH_FOREST) mutatedBiomeId = BIRCH_FOREST_HILLS;
else if (originalBiomeId == DARK_FOREST) mutatedBiomeId = PLAINS;
else if (originalBiomeId == TAIGA) mutatedBiomeId = TAIGA_HILLS;
else if (originalBiomeId == GIANT_TREE_TAIGA) mutatedBiomeId = GIANT_TREE_TAIGA_HILLS;
else if (originalBiomeId == SNOWY_TAIGA) mutatedBiomeId = SNOWY_TAIGA_HILLS;
else if (originalBiomeId == PLAINS) mutatedBiomeId = context.random(3) == 0 ? WOODED_HILLS : FOREST;
else if (originalBiomeId == SNOWY_TUNDRA) mutatedBiomeId = SNOWY_MOUNTAINS;
else if (originalBiomeId == JUNGLE) mutatedBiomeId = JUNGLE_HILLS;
else if (originalBiomeId == BOPLayerUtil.OCEAN) mutatedBiomeId = BOPLayerUtil.DEEP_OCEAN;
else if (originalBiomeId == BOPLayerUtil.LUKEWARM_OCEAN) mutatedBiomeId = BOPLayerUtil.DEEP_LUKEWARM_OCEAN;
else if (originalBiomeId == BOPLayerUtil.COLD_OCEAN) mutatedBiomeId = BOPLayerUtil.DEEP_COLD_OCEAN;
else if (originalBiomeId == BOPLayerUtil.FROZEN_OCEAN) mutatedBiomeId = BOPLayerUtil.DEEP_FROZEN_OCEAN;
else if (originalBiomeId == MOUNTAINS) mutatedBiomeId = WOODED_MOUNTAINS;
else if (originalBiomeId == SAVANNA) mutatedBiomeId = SAVANA_PLATEAU;
else if (LayerUtil.areBiomesSimilar(originalBiomeId, WOODED_BADLANDS_PLATEAU)) mutatedBiomeId = BADLANDS;
else if ((originalBiomeId == BOPLayerUtil.DEEP_OCEAN || originalBiomeId == BOPLayerUtil.DEEP_LUKEWARM_OCEAN || originalBiomeId == BOPLayerUtil.DEEP_COLD_OCEAN || originalBiomeId == BOPLayerUtil.DEEP_FROZEN_OCEAN) && context.random(3) == 0)
{
mutatedBiomeId = context.random(2) == 0 ? PLAINS : FOREST;
}
return mutatedBiomeId;
}
}

View File

@ -65,7 +65,11 @@ import biomesoplenty.common.biome.overworld.WhiteBeachBiome;
import biomesoplenty.common.biome.overworld.WoodlandBiome;
import biomesoplenty.common.biome.overworld.XericShrublandBiome;
import biomesoplenty.common.world.WorldTypeBOP;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.init.Biomes;
import net.minecraft.item.Item;
import net.minecraft.util.registry.IRegistry;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.registries.ForgeRegistries;
@ -76,6 +80,8 @@ public class ModBiomes
{
public static WorldTypeBOP worldType;
public static Multimap<Integer, WeightedSubBiome> subBiomes = HashMultimap.create();
public static void init()
{
worldType = new WorldTypeBOP();
@ -138,6 +144,9 @@ public class ModBiomes
white_beach = registerBiome(new WhiteBeachBiome(), "white_beach");
woodland = registerBiome(new WoodlandBiome(), "woodland");
xeric_shrubland = registerBiome(new XericShrublandBiome(), "xeric_shrubland");
// Note: Rarity supports two decimal places
registerSubBiome(Biomes.PLAINS, overgrown_cliffs, 1.00f, 100);
}
public static Optional<Biome> registerBiome(BiomeBOP biome, String name)
@ -157,4 +166,26 @@ public class ModBiomes
return Optional.of(biome);
}
public static void registerSubBiome(Biome parent, Optional<Biome> child, float rarity, int weight)
{
if (!child.isPresent())
return;
subBiomes.put(IRegistry.BIOME.getId(parent), new WeightedSubBiome(child.get(), rarity, weight));
}
public static class WeightedSubBiome
{
public final Biome biome;
public final float rarity;
public final int weight;
public WeightedSubBiome(Biome biome, float rarity, int weight)
{
this.biome = biome;
this.rarity = rarity;
this.weight = weight;
}
}
}