Biome API (WIP), javadocs, biome map
This commit is contained in:
parent
c89235ec92
commit
67c9c2302d
9 changed files with 424 additions and 38 deletions
|
@ -2,8 +2,10 @@ package ru.bclib.util;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
@ -11,6 +13,15 @@ import net.minecraft.world.level.block.Block;
|
||||||
public class BonemealUtil {
|
public class BonemealUtil {
|
||||||
private static final Map<ResourceLocation, Map<Block, WeightedList<Block>>> GRASS_BIOMES = Maps.newHashMap();
|
private static final Map<ResourceLocation, Map<Block, WeightedList<Block>>> GRASS_BIOMES = Maps.newHashMap();
|
||||||
private static final Map<Block, WeightedList<Block>> GRASS_TYPES = Maps.newHashMap();
|
private static final Map<Block, WeightedList<Block>> GRASS_TYPES = Maps.newHashMap();
|
||||||
|
private static final Set<Block> SPREADABLE_BLOCKS = Sets.newHashSet();
|
||||||
|
|
||||||
|
public static void addSpreadableBlock(Block block) {
|
||||||
|
SPREADABLE_BLOCKS.add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSpreadable(Block block) {
|
||||||
|
return SPREADABLE_BLOCKS.contains(block);
|
||||||
|
}
|
||||||
|
|
||||||
public static void addBonemealGrass(Block terrain, Block plant) {
|
public static void addBonemealGrass(Block terrain, Block plant) {
|
||||||
addBonemealGrass(terrain, plant, 1F);
|
addBonemealGrass(terrain, plant, 1F);
|
||||||
|
|
74
src/main/java/ru/bclib/util/WeighTree.java
Normal file
74
src/main/java/ru/bclib/util/WeighTree.java
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package ru.bclib.util;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class WeighTree<T> {
|
||||||
|
private final float maxWeight;
|
||||||
|
private final Node root;
|
||||||
|
|
||||||
|
public WeighTree(WeightedList<T> list) {
|
||||||
|
maxWeight = list.getMaxWeight();
|
||||||
|
root = getNode(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get eandom value from tree.
|
||||||
|
* @param random - {@link Random}.
|
||||||
|
* @return {@link T} value.
|
||||||
|
*/
|
||||||
|
public T get(Random random) {
|
||||||
|
return root.get(random.nextFloat() * maxWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node getNode(WeightedList<T> biomes) {
|
||||||
|
int size = biomes.size();
|
||||||
|
if (size == 1) {
|
||||||
|
return new Leaf(biomes.get(0));
|
||||||
|
}
|
||||||
|
else if (size == 2) {
|
||||||
|
T first = biomes.get(0);
|
||||||
|
return new Branch(biomes.getWeight(0), new Leaf(first), new Leaf(biomes.get(1)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int index = size >> 1;
|
||||||
|
float separator = biomes.getWeight(index);
|
||||||
|
Node a = getNode(biomes.subList(0, index + 1));
|
||||||
|
Node b = getNode(biomes.subList(index, size));
|
||||||
|
return new Branch(separator, a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class Node {
|
||||||
|
abstract T get(float value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Branch extends Node {
|
||||||
|
final float separator;
|
||||||
|
final Node min;
|
||||||
|
final Node max;
|
||||||
|
|
||||||
|
public Branch(float separator, Node min, Node max) {
|
||||||
|
this.separator = separator;
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
T get(float value) {
|
||||||
|
return value < separator ? min.get(value) : max.get(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Leaf extends Node {
|
||||||
|
final T biome;
|
||||||
|
|
||||||
|
Leaf(T biome) {
|
||||||
|
this.biome = biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
T get(float value) {
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,18 +3,29 @@ package ru.bclib.util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class WeightedList<T> {
|
public class WeightedList<T> {
|
||||||
private final List<Float> weights = new ArrayList<Float>();
|
private final List<Float> weights = new ArrayList<Float>();
|
||||||
private final List<T> values = new ArrayList<T>();
|
private final List<T> values = new ArrayList<T>();
|
||||||
private float maxWeight;
|
private float maxWeight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds value with specified weight to the list
|
||||||
|
* @param value
|
||||||
|
* @param weight
|
||||||
|
*/
|
||||||
public void add(T value, float weight) {
|
public void add(T value, float weight) {
|
||||||
maxWeight += weight;
|
maxWeight += weight;
|
||||||
weights.add(maxWeight);
|
weights.add(maxWeight);
|
||||||
values.add(value);
|
values.add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get random value.
|
||||||
|
* @param random - {@link Random}.
|
||||||
|
* @return {@link T} value.
|
||||||
|
*/
|
||||||
public T get(Random random) {
|
public T get(Random random) {
|
||||||
if (maxWeight < 1) {
|
if (maxWeight < 1) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -27,8 +38,79 @@ public class WeightedList<T> {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value by index.
|
||||||
|
* @param index - {@code int} index.
|
||||||
|
* @return {@link T} value.
|
||||||
|
*/
|
||||||
|
public T get(int index) {
|
||||||
|
return values.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value weight. Weight is summed with all previous values weights.
|
||||||
|
* @param index - {@code int} index.
|
||||||
|
* @return {@code float} weight.
|
||||||
|
*/
|
||||||
|
public float getWeight(int index) {
|
||||||
|
return weights.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chech if the list is empty.
|
||||||
|
* @return {@code true} if list is empty and {@code false} if not.
|
||||||
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return maxWeight == 0;
|
return maxWeight == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list size.
|
||||||
|
* @return {@code int} list size.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return values.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a sublist of this list with same weights. Used only in {@link WeighTree}
|
||||||
|
* @param start - {@code int} start index (inclusive).
|
||||||
|
* @param end - {@code int} end index (exclusive).
|
||||||
|
* @return {@link WeightedList<T>}.
|
||||||
|
*/
|
||||||
|
protected WeightedList<T> subList(int start, int end) {
|
||||||
|
WeightedList<T> list = new WeightedList<T>();
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
list.weights.add(weights.get(i));
|
||||||
|
list.values.add(values.get(i));
|
||||||
|
}
|
||||||
|
list.maxWeight = list.weights.get(end - 1);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if list contains certain value.
|
||||||
|
* @param value - {@link T} value.
|
||||||
|
* @return {@code true} if value is in list and {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean contains(T value) {
|
||||||
|
return values.contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies {@link Consumer} to all values in list.
|
||||||
|
* @param function - {@link Consumer}.
|
||||||
|
*/
|
||||||
|
public void forEach(Consumer<T> function) {
|
||||||
|
values.forEach(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum weight of the tree.
|
||||||
|
* @return {@code float} maximum weight.
|
||||||
|
*/
|
||||||
|
public float getMaxWeight() {
|
||||||
|
return maxWeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,16 @@ import com.google.gson.JsonObject;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
import ru.bclib.config.IdConfig;
|
|
||||||
import ru.bclib.util.JsonFactory;
|
import ru.bclib.util.JsonFactory;
|
||||||
import ru.bclib.util.StructureHelper;
|
import ru.bclib.util.StructureHelper;
|
||||||
|
import ru.bclib.util.WeightedList;
|
||||||
import ru.bclib.world.features.BCLFeature;
|
import ru.bclib.world.features.BCLFeature;
|
||||||
import ru.bclib.world.features.ListFeature;
|
import ru.bclib.world.features.ListFeature;
|
||||||
import ru.bclib.world.features.ListFeature.StructureInfo;
|
import ru.bclib.world.features.ListFeature.StructureInfo;
|
||||||
import ru.bclib.world.features.NBTStructureFeature.TerrainMerge;
|
import ru.bclib.world.features.NBTStructureFeature.TerrainMerge;
|
||||||
|
|
||||||
public class BCLBiome {
|
public class BCLBiome {
|
||||||
protected List<BCLBiome> subbiomes = Lists.newArrayList();
|
protected WeightedList<BCLBiome> subbiomes = new WeightedList<BCLBiome>();
|
||||||
|
|
||||||
protected final Biome biome;
|
protected final Biome biome;
|
||||||
protected final ResourceLocation mcID;
|
protected final ResourceLocation mcID;
|
||||||
|
@ -29,32 +29,29 @@ public class BCLBiome {
|
||||||
|
|
||||||
protected BCLBiome biomeParent;
|
protected BCLBiome biomeParent;
|
||||||
protected float maxSubBiomeChance = 1;
|
protected float maxSubBiomeChance = 1;
|
||||||
protected final float genChanceUnmutable;
|
protected final float genChance;
|
||||||
protected float genChance = 1;
|
|
||||||
|
|
||||||
private final float fogDensity;
|
private final float fogDensity;
|
||||||
private BCLFeature structuresFeature;
|
private BCLFeature structuresFeature;
|
||||||
private Biome actualBiome;
|
private Biome actualBiome;
|
||||||
|
|
||||||
public BCLBiome(BiomeDefinition definition, IdConfig config) {
|
public BCLBiome(BiomeDefinition definition) {
|
||||||
this.mcID = definition.getID();
|
this.mcID = definition.getID();
|
||||||
this.readStructureList();
|
this.readStructureList();
|
||||||
if (structuresFeature != null) {
|
if (structuresFeature != null) {
|
||||||
definition.addFeature(structuresFeature);
|
definition.addFeature(structuresFeature);
|
||||||
}
|
}
|
||||||
this.biome = definition.build();
|
this.biome = definition.build();
|
||||||
this.fogDensity = config.getFloat(mcID, "fog_density", definition.getFodDensity());
|
this.genChance = definition.getGenChance();
|
||||||
this.genChanceUnmutable = config.getFloat(mcID, "generation_chance", definition.getGenChance());
|
this.fogDensity = definition.getFodDensity();
|
||||||
this.edgeSize = config.getInt(mcID, "edge_size", 32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.mcID = id;
|
||||||
this.readStructureList();
|
|
||||||
this.biome = biome;
|
this.biome = biome;
|
||||||
this.fogDensity = config.getFloat(mcID, "fog_density", fogDensity);
|
this.genChance = genChance;
|
||||||
this.genChanceUnmutable = config.getFloat(mcID, "generation_chance", genChance);
|
this.fogDensity = fogDensity;
|
||||||
this.edgeSize = config.getInt(mcID, "edge_size", 32);
|
this.readStructureList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BCLBiome getEdge() {
|
public BCLBiome getEdge() {
|
||||||
|
@ -75,9 +72,8 @@ public class BCLBiome {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSubBiome(BCLBiome biome) {
|
public void addSubBiome(BCLBiome biome) {
|
||||||
maxSubBiomeChance += biome.mutateGenChance(maxSubBiomeChance);
|
|
||||||
biome.biomeParent = this;
|
biome.biomeParent = this;
|
||||||
subbiomes.add(biome);
|
subbiomes.add(biome, biome.getGenChance());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsSubBiome(BCLBiome biome) {
|
public boolean containsSubBiome(BCLBiome biome) {
|
||||||
|
@ -85,11 +81,7 @@ public class BCLBiome {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BCLBiome getSubBiome(Random random) {
|
public BCLBiome getSubBiome(Random random) {
|
||||||
float chance = random.nextFloat() * maxSubBiomeChance;
|
return subbiomes.get(random);
|
||||||
for (BCLBiome biome : subbiomes)
|
|
||||||
if (biome.canGenerate(chance))
|
|
||||||
return biome;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BCLBiome getParentBiome() {
|
public BCLBiome getParentBiome() {
|
||||||
|
@ -108,16 +100,6 @@ public class BCLBiome {
|
||||||
return biome == this || (biome.hasParentBiome() && biome.getParentBiome() == this);
|
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() {
|
public Biome getBiome() {
|
||||||
return biome;
|
return biome;
|
||||||
}
|
}
|
||||||
|
@ -172,10 +154,6 @@ public class BCLBiome {
|
||||||
return this.genChance;
|
return this.genChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getGenChanceImmutable() {
|
|
||||||
return this.genChanceUnmutable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateActualBiomes(Registry<Biome> biomeRegistry) {
|
public void updateActualBiomes(Registry<Biome> biomeRegistry) {
|
||||||
subbiomes.forEach((sub) -> {
|
subbiomes.forEach((sub) -> {
|
||||||
if (sub != this) {
|
if (sub != this) {
|
||||||
|
|
|
@ -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.ConfiguredSurfaceBuilder;
|
||||||
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder;
|
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder;
|
||||||
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration;
|
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration;
|
||||||
|
import ru.bclib.config.IdConfig;
|
||||||
import ru.bclib.util.ColorUtil;
|
import ru.bclib.util.ColorUtil;
|
||||||
import ru.bclib.world.features.BCLFeature;
|
import ru.bclib.world.features.BCLFeature;
|
||||||
import ru.bclib.world.structures.BCLStructureFeature;
|
import ru.bclib.world.structures.BCLStructureFeature;
|
||||||
|
@ -85,8 +86,8 @@ public class BiomeDefinition {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create default definition for The Nether biome.
|
* Create default definition for The Nether biome.
|
||||||
* @param id
|
* @param id - {@ResourceLocation}.
|
||||||
* @return
|
* @return {@link BiomeDefinition}.
|
||||||
*/
|
*/
|
||||||
public static BiomeDefinition netherBiome(ResourceLocation id) {
|
public static BiomeDefinition netherBiome(ResourceLocation id) {
|
||||||
BiomeDefinition def = new BiomeDefinition(id);
|
BiomeDefinition def = new BiomeDefinition(id);
|
||||||
|
@ -98,8 +99,8 @@ public class BiomeDefinition {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create default definition for The End biome.
|
* Create default definition for The End biome.
|
||||||
* @param id
|
* @param id - {@ResourceLocation}.
|
||||||
* @return
|
* @return {@link BiomeDefinition}.
|
||||||
*/
|
*/
|
||||||
public static BiomeDefinition endBiome(ResourceLocation id) {
|
public static BiomeDefinition endBiome(ResourceLocation id) {
|
||||||
BiomeDefinition def = new BiomeDefinition(id);
|
BiomeDefinition def = new BiomeDefinition(id);
|
||||||
|
@ -109,6 +110,23 @@ public class BiomeDefinition {
|
||||||
return def;
|
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) {
|
public BiomeDefinition setCategory(BiomeCategory category) {
|
||||||
this.category = category;
|
this.category = category;
|
||||||
return this;
|
return this;
|
||||||
|
|
35
src/main/java/ru/bclib/world/generator/BiomeChunk.java
Normal file
35
src/main/java/ru/bclib/world/generator/BiomeChunk.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
113
src/main/java/ru/bclib/world/generator/BiomeMap.java
Normal file
113
src/main/java/ru/bclib/world/generator/BiomeMap.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
69
src/main/java/ru/bclib/world/generator/BiomePicker.java
Normal file
69
src/main/java/ru/bclib/world/generator/BiomePicker.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
6
src/main/java/ru/bclib/world/generator/BiomeType.java
Normal file
6
src/main/java/ru/bclib/world/generator/BiomeType.java
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package ru.bclib.world.generator;
|
||||||
|
|
||||||
|
public enum BiomeType {
|
||||||
|
LAND,
|
||||||
|
VOID;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue