Biome API (WIP), javadocs, biome map

This commit is contained in:
paulevsGitch 2021-05-23 09:58:27 +03:00
parent c89235ec92
commit 67c9c2302d
9 changed files with 424 additions and 38 deletions

View file

@ -11,16 +11,16 @@ import com.google.gson.JsonObject;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import ru.bclib.config.IdConfig;
import ru.bclib.util.JsonFactory;
import ru.bclib.util.StructureHelper;
import ru.bclib.util.WeightedList;
import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.features.ListFeature;
import ru.bclib.world.features.ListFeature.StructureInfo;
import ru.bclib.world.features.NBTStructureFeature.TerrainMerge;
public class BCLBiome {
protected List<BCLBiome> subbiomes = Lists.newArrayList();
protected WeightedList<BCLBiome> subbiomes = new WeightedList<BCLBiome>();
protected final Biome biome;
protected final ResourceLocation mcID;
@ -29,32 +29,29 @@ public class BCLBiome {
protected BCLBiome biomeParent;
protected float maxSubBiomeChance = 1;
protected final float genChanceUnmutable;
protected float genChance = 1;
protected final float genChance;
private final float fogDensity;
private BCLFeature structuresFeature;
private Biome actualBiome;
public BCLBiome(BiomeDefinition definition, IdConfig config) {
public BCLBiome(BiomeDefinition definition) {
this.mcID = definition.getID();
this.readStructureList();
if (structuresFeature != null) {
definition.addFeature(structuresFeature);
}
this.biome = definition.build();
this.fogDensity = config.getFloat(mcID, "fog_density", definition.getFodDensity());
this.genChanceUnmutable = config.getFloat(mcID, "generation_chance", definition.getGenChance());
this.edgeSize = config.getInt(mcID, "edge_size", 32);
this.genChance = definition.getGenChance();
this.fogDensity = definition.getFodDensity();
}
public BCLBiome(ResourceLocation id, Biome biome, float fogDensity, float genChance, boolean hasCaves, IdConfig config) {
public BCLBiome(ResourceLocation id, Biome biome, float fogDensity, float genChance) {
this.mcID = id;
this.readStructureList();
this.biome = biome;
this.fogDensity = config.getFloat(mcID, "fog_density", fogDensity);
this.genChanceUnmutable = config.getFloat(mcID, "generation_chance", genChance);
this.edgeSize = config.getInt(mcID, "edge_size", 32);
this.genChance = genChance;
this.fogDensity = fogDensity;
this.readStructureList();
}
public BCLBiome getEdge() {
@ -75,9 +72,8 @@ public class BCLBiome {
}
public void addSubBiome(BCLBiome biome) {
maxSubBiomeChance += biome.mutateGenChance(maxSubBiomeChance);
biome.biomeParent = this;
subbiomes.add(biome);
subbiomes.add(biome, biome.getGenChance());
}
public boolean containsSubBiome(BCLBiome biome) {
@ -85,11 +81,7 @@ public class BCLBiome {
}
public BCLBiome getSubBiome(Random random) {
float chance = random.nextFloat() * maxSubBiomeChance;
for (BCLBiome biome : subbiomes)
if (biome.canGenerate(chance))
return biome;
return this;
return subbiomes.get(random);
}
public BCLBiome getParentBiome() {
@ -108,16 +100,6 @@ public class BCLBiome {
return biome == this || (biome.hasParentBiome() && biome.getParentBiome() == this);
}
public boolean canGenerate(float chance) {
return chance <= this.genChance;
}
public float mutateGenChance(float chance) {
genChance = genChanceUnmutable;
genChance += chance;
return genChance;
}
public Biome getBiome() {
return biome;
}
@ -172,10 +154,6 @@ public class BCLBiome {
return this.genChance;
}
public float getGenChanceImmutable() {
return this.genChanceUnmutable;
}
public void updateActualBiomes(Registry<Biome> biomeRegistry) {
subbiomes.forEach((sub) -> {
if (sub != this) {

View file

@ -34,6 +34,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.ProbabilityFeat
import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder;
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration;
import ru.bclib.config.IdConfig;
import ru.bclib.util.ColorUtil;
import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.structures.BCLStructureFeature;
@ -85,8 +86,8 @@ public class BiomeDefinition {
/**
* Create default definition for The Nether biome.
* @param id
* @return
* @param id - {@ResourceLocation}.
* @return {@link BiomeDefinition}.
*/
public static BiomeDefinition netherBiome(ResourceLocation id) {
BiomeDefinition def = new BiomeDefinition(id);
@ -98,8 +99,8 @@ public class BiomeDefinition {
/**
* Create default definition for The End biome.
* @param id
* @return
* @param id - {@ResourceLocation}.
* @return {@link BiomeDefinition}.
*/
public static BiomeDefinition endBiome(ResourceLocation id) {
BiomeDefinition def = new BiomeDefinition(id);
@ -109,6 +110,23 @@ public class BiomeDefinition {
return def;
}
/**
* Used to load biome settings from config.
* @param config - {@link IdConfig}.
* @return this {@link BiomeDefinition}.
*/
public BiomeDefinition loadConfigValues(IdConfig config) {
this.fogDensity = config.getFloat(id, "fog_density", this.fogDensity);
this.genChance = config.getFloat(id, "generation_chance", this.genChance);
this.edgeSize = config.getInt(id, "edge_size", this.edgeSize);
return this;
}
/**
* Set category of the biome.
* @param category - {@link BiomeCategory}.
* @return this {@link BiomeDefinition}.
*/
public BiomeDefinition setCategory(BiomeCategory category) {
this.category = category;
return this;

View file

@ -0,0 +1,35 @@
package ru.bclib.world.generator;
import java.util.Random;
import ru.bclib.world.biomes.BCLBiome;
public class BiomeChunk {
protected static final int WIDTH = 16;
private static final int SM_WIDTH = WIDTH >> 1;
private static final int MASK_OFFSET = SM_WIDTH - 1;
protected static final int MASK_WIDTH = WIDTH - 1;
private final BCLBiome[][] biomes;
public BiomeChunk(BiomeMap map, Random random, BiomePicker picker) {
BCLBiome[][] PreBio = new BCLBiome[SM_WIDTH][SM_WIDTH];
biomes = new BCLBiome[WIDTH][WIDTH];
for (int x = 0; x < SM_WIDTH; x++)
for (int z = 0; z < SM_WIDTH; z++)
PreBio[x][z] = picker.getBiome(random);
for (int x = 0; x < WIDTH; x++)
for (int z = 0; z < WIDTH; z++)
biomes[x][z] = PreBio[offsetXZ(x, random)][offsetXZ(z, random)].getSubBiome(random);
}
public BCLBiome getBiome(int x, int z) {
return biomes[x & MASK_WIDTH][z & MASK_WIDTH];
}
private int offsetXZ(int x, Random random) {
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
}
}

View file

@ -0,0 +1,113 @@
package ru.bclib.world.generator;
import java.util.Map;
import com.google.common.collect.Maps;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import ru.bclib.noise.OpenSimplexNoise;
import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome;
public class BiomeMap {
private static final WorldgenRandom RANDOM = new WorldgenRandom();
private final Map<ChunkPos, BiomeChunk> maps = Maps.newHashMap();
private final int size;
private final int sizeXZ;
private final int depth;
private final OpenSimplexNoise noiseX;
private final OpenSimplexNoise noiseZ;
private final BiomePicker picker;
private final long seed;
public BiomeMap(long seed, int size, BiomePicker picker) {
maps.clear();
RANDOM.setSeed(seed);
noiseX = new OpenSimplexNoise(RANDOM.nextLong());
noiseZ = new OpenSimplexNoise(RANDOM.nextLong());
this.sizeXZ = size;
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
this.size = 1 << depth;
this.picker = picker;
this.seed = seed;
}
public long getSeed() {
return seed;
}
public void clearCache() {
if (maps.size() > 32) {
maps.clear();
}
}
private BCLBiome getRawBiome(int bx, int bz) {
double x = (double) bx * size / sizeXZ;
double z = (double) bz * size / sizeXZ;
double nx = x;
double nz = z;
double px = bx * 0.2;
double pz = bz * 0.2;
for (int i = 0; i < depth; i++) {
nx = (x + noiseX.eval(px, pz)) / 2F;
nz = (z + noiseZ.eval(px, pz)) / 2F;
x = nx;
z = nz;
px = px / 2 + i;
pz = pz / 2 + i;
}
bx = MHelper.floor(x);
bz = MHelper.floor(z);
if ((bx & BiomeChunk.MASK_WIDTH) == BiomeChunk.MASK_WIDTH) {
x += (bz / 2) & 1;
}
if ((bz & BiomeChunk.MASK_WIDTH) == BiomeChunk.MASK_WIDTH) {
z += (bx / 2) & 1;
}
ChunkPos cpos = new ChunkPos(MHelper.floor(x / BiomeChunk.WIDTH), MHelper.floor(z / BiomeChunk.WIDTH));
BiomeChunk chunk = maps.get(cpos);
if (chunk == null) {
RANDOM.setBaseChunkSeed(cpos.x, cpos.z);
chunk = new BiomeChunk(this, RANDOM, picker);
maps.put(cpos, chunk);
}
return chunk.getBiome(MHelper.floor(x), MHelper.floor(z));
}
public BCLBiome getBiome(int x, int z) {
BCLBiome biome = getRawBiome(x, z);
if (biome.hasEdge() || (biome.hasParentBiome() && biome.getParentBiome().hasEdge())) {
BCLBiome search = biome;
if (biome.hasParentBiome()) {
search = biome.getParentBiome();
}
int d = (int) Math.ceil(search.getEdgeSize() / 4F) << 2;
boolean edge = !search.isSame(getRawBiome(x + d, z));
edge = edge || !search.isSame(getRawBiome(x - d, z));
edge = edge || !search.isSame(getRawBiome(x, z + d));
edge = edge || !search.isSame(getRawBiome(x, z - d));
edge = edge || !search.isSame(getRawBiome(x - 1, z - 1));
edge = edge || !search.isSame(getRawBiome(x - 1, z + 1));
edge = edge || !search.isSame(getRawBiome(x + 1, z - 1));
edge = edge || !search.isSame(getRawBiome(x + 1, z + 1));
if (edge) {
biome = search.getEdge();
}
}
return biome;
}
}

View file

@ -0,0 +1,69 @@
package ru.bclib.world.generator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import net.minecraft.resources.ResourceLocation;
import ru.bclib.util.WeighTree;
import ru.bclib.util.WeightedList;
import ru.bclib.world.biomes.BCLBiome;
public class BiomePicker {
private final Set<ResourceLocation> immutableIDs = Sets.newHashSet();
private final List<BCLBiome> biomes = Lists.newArrayList();
private int biomeCount = 0;
private WeighTree<BCLBiome> tree;
public void addBiome(BCLBiome biome) {
immutableIDs.add(biome.getID());
biomes.add(biome);
biomeCount ++;
}
public void addBiomeMutable(BCLBiome biome) {
biomes.add(biome);
}
public void clearMutables() {
for (int i = biomes.size() - 1; i >= biomeCount; i--) {
biomes.remove(i);
}
}
public BCLBiome getBiome(Random random) {
return biomes.isEmpty() ? null : tree.get(random);
}
public List<BCLBiome> getBiomes() {
return biomes;
}
public boolean containsImmutable(ResourceLocation id) {
return immutableIDs.contains(id);
}
public void removeMutableBiome(ResourceLocation id) {
for (int i = biomeCount; i < biomes.size(); i++) {
BCLBiome biome = biomes.get(i);
if (biome.getID().equals(id)) {
biomes.remove(i);
break;
}
}
}
public void rebuild() {
if (biomes.isEmpty()) {
return;
}
WeightedList<BCLBiome> list = new WeightedList<BCLBiome>();
biomes.forEach((biome) -> {
list.add(biome, biome.getGenChance());
});
tree = new WeighTree<BCLBiome>(list);
}
}

View file

@ -0,0 +1,6 @@
package ru.bclib.world.generator;
public enum BiomeType {
LAND,
VOID;
}