Hexagonal biome generator
This commit is contained in:
parent
c7c11d0b4c
commit
211d0fc751
6 changed files with 465 additions and 173 deletions
|
@ -20,6 +20,7 @@ import ru.bclib.config.ConfigKeeper.StringArrayEntry;
|
||||||
import ru.bclib.config.Configs;
|
import ru.bclib.config.Configs;
|
||||||
import ru.bclib.noise.OpenSimplexNoise;
|
import ru.bclib.noise.OpenSimplexNoise;
|
||||||
import ru.bclib.world.biomes.BCLBiome;
|
import ru.bclib.world.biomes.BCLBiome;
|
||||||
|
import ru.bclib.world.generator.map.hex.HexBiomeMap;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -39,8 +40,8 @@ public class BCLibEndBiomeSource extends BiomeSource {
|
||||||
private final SimplexNoise noise;
|
private final SimplexNoise noise;
|
||||||
private final Biome centerBiome;
|
private final Biome centerBiome;
|
||||||
private final Biome barrens;
|
private final Biome barrens;
|
||||||
private BiomeMap mapLand;
|
private HexBiomeMap mapLand;
|
||||||
private BiomeMap mapVoid;
|
private HexBiomeMap mapVoid;
|
||||||
private final long seed;
|
private final long seed;
|
||||||
private final Point pos;
|
private final Point pos;
|
||||||
|
|
||||||
|
@ -74,8 +75,8 @@ public class BCLibEndBiomeSource extends BiomeSource {
|
||||||
BiomeAPI.END_LAND_BIOME_PICKER.rebuild();
|
BiomeAPI.END_LAND_BIOME_PICKER.rebuild();
|
||||||
BiomeAPI.END_VOID_BIOME_PICKER.rebuild();
|
BiomeAPI.END_VOID_BIOME_PICKER.rebuild();
|
||||||
|
|
||||||
this.mapLand = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.END_LAND_BIOME_PICKER);
|
this.mapLand = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.END_LAND_BIOME_PICKER);
|
||||||
this.mapVoid = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER);
|
this.mapVoid = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER);
|
||||||
this.centerBiome = biomeRegistry.getOrThrow(Biomes.THE_END);
|
this.centerBiome = biomeRegistry.getOrThrow(Biomes.THE_END);
|
||||||
this.barrens = biomeRegistry.getOrThrow(Biomes.END_BARRENS);
|
this.barrens = biomeRegistry.getOrThrow(Biomes.END_BARRENS);
|
||||||
this.biomeRegistry = biomeRegistry;
|
this.biomeRegistry = biomeRegistry;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import ru.bclib.api.biomes.BiomeAPI;
|
||||||
import ru.bclib.config.ConfigKeeper.StringArrayEntry;
|
import ru.bclib.config.ConfigKeeper.StringArrayEntry;
|
||||||
import ru.bclib.config.Configs;
|
import ru.bclib.config.Configs;
|
||||||
import ru.bclib.world.biomes.BCLBiome;
|
import ru.bclib.world.biomes.BCLBiome;
|
||||||
|
import ru.bclib.world.generator.map.hex.HexBiomeMap;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -28,7 +29,7 @@ public class BCLibNetherBiomeSource extends BiomeSource {
|
||||||
})).apply(instance, instance.stable(BCLibNetherBiomeSource::new));
|
})).apply(instance, instance.stable(BCLibNetherBiomeSource::new));
|
||||||
});
|
});
|
||||||
private final Registry<Biome> biomeRegistry;
|
private final Registry<Biome> biomeRegistry;
|
||||||
private BiomeMap biomeMap;
|
private HexBiomeMap biomeMap;
|
||||||
private final long seed;
|
private final long seed;
|
||||||
|
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
|
@ -59,7 +60,7 @@ public class BCLibNetherBiomeSource extends BiomeSource {
|
||||||
BiomeAPI.NETHER_BIOME_PICKER.getBiomes().forEach(biome -> biome.updateActualBiomes(biomeRegistry));
|
BiomeAPI.NETHER_BIOME_PICKER.getBiomes().forEach(biome -> biome.updateActualBiomes(biomeRegistry));
|
||||||
BiomeAPI.NETHER_BIOME_PICKER.rebuild();
|
BiomeAPI.NETHER_BIOME_PICKER.rebuild();
|
||||||
|
|
||||||
this.biomeMap = new BiomeMap(seed, GeneratorOptions.getBiomeSizeNether(), BiomeAPI.NETHER_BIOME_PICKER);
|
this.biomeMap = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeNether(), BiomeAPI.NETHER_BIOME_PICKER);
|
||||||
this.biomeRegistry = biomeRegistry;
|
this.biomeRegistry = biomeRegistry;
|
||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
package ru.bclib.world.generator.map.hex;
|
||||||
|
|
||||||
|
import ru.bclib.world.biomes.BCLBiome;
|
||||||
|
import ru.bclib.world.generator.BiomePicker;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class HexBiomeChunk {
|
||||||
|
private static final short SIDE = 32;
|
||||||
|
private static final short SIZE = SIDE * SIDE;
|
||||||
|
private static final byte SIDE_MASK = SIDE - 1;
|
||||||
|
private static final byte SIDE_OFFSET = (byte) Math.round(Math.log(SIDE) / Math.log(2));
|
||||||
|
private static final short[][] NEIGHBOURS;
|
||||||
|
public static final short SCALE = SIDE / 4;
|
||||||
|
|
||||||
|
private final BCLBiome[] biomes;
|
||||||
|
|
||||||
|
public HexBiomeChunk(Random random, BiomePicker picker) {
|
||||||
|
BCLBiome[][] buffers = new BCLBiome[2][SIZE];
|
||||||
|
|
||||||
|
byte scale = SIDE / 4;
|
||||||
|
for (byte x = 0; x < 4; x++) {
|
||||||
|
for (byte z = 0; z < 4; z++) {
|
||||||
|
byte px = (byte) (x * scale + random.nextInt(scale));
|
||||||
|
byte pz = (byte) (z * scale + random.nextInt(scale));
|
||||||
|
circle(buffers[0], getIndex(px, pz), picker.getBiome(random), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
short maxSide = SIZE - SIDE;
|
||||||
|
boolean hasEmptyCells = true;
|
||||||
|
byte bufferIndex = 0;
|
||||||
|
while (hasEmptyCells) {
|
||||||
|
BCLBiome[] inBuffer = buffers[bufferIndex];
|
||||||
|
bufferIndex = (byte) ((bufferIndex + 1) & 1);
|
||||||
|
BCLBiome[] outBuffer = buffers[bufferIndex];
|
||||||
|
hasEmptyCells = false;
|
||||||
|
|
||||||
|
for (short index = SIDE; index < maxSide; index++) {
|
||||||
|
byte z = (byte) (index & SIDE_MASK);
|
||||||
|
if (z == 0 || z == SIDE_MASK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inBuffer[index] != null) {
|
||||||
|
outBuffer[index] = inBuffer[index];
|
||||||
|
short[] neighbours = getNeighbours(index & SIDE_MASK);
|
||||||
|
short indexSide = (short) (index + neighbours[random.nextInt(6)]);
|
||||||
|
if (indexSide >= 0 && indexSide < SIZE && outBuffer[indexSide] == null) {
|
||||||
|
outBuffer[indexSide] = inBuffer[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hasEmptyCells = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BCLBiome[] outBuffer = buffers[bufferIndex];
|
||||||
|
byte preN = (byte) (SIDE_MASK - 2);
|
||||||
|
for (byte index = 0; index < SIDE; index++) {
|
||||||
|
outBuffer[getIndex(index, (byte) 0)] = outBuffer[getIndex(index, (byte) 2)];
|
||||||
|
outBuffer[getIndex((byte) 0, index)] = outBuffer[getIndex((byte) 2, index)];
|
||||||
|
outBuffer[getIndex(index, SIDE_MASK)] = outBuffer[getIndex(index, preN)];
|
||||||
|
outBuffer[getIndex(SIDE_MASK, index)] = outBuffer[getIndex(preN, index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (short index = 0; index < SIZE; index++) {
|
||||||
|
if (random.nextInt(4) == 0) {
|
||||||
|
circle(outBuffer, index, outBuffer[index].getSubBiome(random), outBuffer[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.biomes = outBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void circle(BCLBiome[] buffer, short center, BCLBiome biome, BCLBiome mask) {
|
||||||
|
if (buffer[center] == mask) {
|
||||||
|
buffer[center] = biome;
|
||||||
|
}
|
||||||
|
short[] neighbours = getNeighbours(center & SIDE_MASK);
|
||||||
|
for (short i: neighbours) {
|
||||||
|
short index = (short) (center + i);
|
||||||
|
if (index >= 0 && index < SIZE && buffer[index] == mask) {
|
||||||
|
buffer[index] = biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte wrap(int value) {
|
||||||
|
return (byte) (value & SIDE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private short getIndex(byte x, byte z) {
|
||||||
|
return (short) ((short) x << SIDE_OFFSET | z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BCLBiome getBiome(int x, int z) {
|
||||||
|
return biomes[getIndex(wrap(x), wrap(z))];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int scaleCoordinate(int value) {
|
||||||
|
return value >> SIDE_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBorder(int value) {
|
||||||
|
return wrap(value) == SIDE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private short[] getNeighbours(int z) {
|
||||||
|
return NEIGHBOURS[z & 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
NEIGHBOURS = new short[2][6];
|
||||||
|
|
||||||
|
NEIGHBOURS[0][0] = 1;
|
||||||
|
NEIGHBOURS[0][1] = -1;
|
||||||
|
NEIGHBOURS[0][2] = SIDE;
|
||||||
|
NEIGHBOURS[0][3] = -SIDE;
|
||||||
|
NEIGHBOURS[0][4] = SIDE + 1;
|
||||||
|
NEIGHBOURS[0][5] = SIDE - 1;
|
||||||
|
|
||||||
|
NEIGHBOURS[1][0] = 1;
|
||||||
|
NEIGHBOURS[1][1] = -1;
|
||||||
|
NEIGHBOURS[1][2] = SIDE;
|
||||||
|
NEIGHBOURS[1][3] = -SIDE;
|
||||||
|
NEIGHBOURS[1][4] = -SIDE + 1;
|
||||||
|
NEIGHBOURS[1][5] = -SIDE - 1;
|
||||||
|
}
|
||||||
|
}
|
156
src/main/java/ru/bclib/world/generator/map/hex/HexBiomeMap.java
Normal file
156
src/main/java/ru/bclib/world/generator/map/hex/HexBiomeMap.java
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
package ru.bclib.world.generator.map.hex;
|
||||||
|
|
||||||
|
import ru.bclib.noise.OpenSimplexNoise;
|
||||||
|
import ru.bclib.util.MHelper;
|
||||||
|
import ru.bclib.world.biomes.BCLBiome;
|
||||||
|
import ru.bclib.world.generator.BiomePicker;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class HexBiomeMap {
|
||||||
|
private static final float RAD_INNER = (float) Math.sqrt(3.0) * 0.5F;
|
||||||
|
private static final float COEF = 0.25F * (float) Math.sqrt(3.0);
|
||||||
|
private static final float COEF_HALF = COEF * 0.5F;
|
||||||
|
private static final float SIN = (float) Math.sin(0.4);
|
||||||
|
private static final float COS = (float) Math.cos(0.4);
|
||||||
|
private static final Random RANDOM = new Random();
|
||||||
|
private static final float[] EDGE_CIRCLE_X;
|
||||||
|
private static final float[] EDGE_CIRCLE_Z;
|
||||||
|
|
||||||
|
private final HashMap<Point, HexBiomeChunk> chunks = new HashMap<>();
|
||||||
|
private final Point selector = new Point();
|
||||||
|
private final BiomePicker picker;
|
||||||
|
|
||||||
|
private final OpenSimplexNoise[] noises = new OpenSimplexNoise[2];
|
||||||
|
private final byte noiseIterations;
|
||||||
|
private final float scale;
|
||||||
|
private final int seed;
|
||||||
|
|
||||||
|
public HexBiomeMap(long seed, int size, BiomePicker picker) {
|
||||||
|
this.picker = picker;
|
||||||
|
this.scale = (float) size / HexBiomeChunk.SCALE;
|
||||||
|
Random random = new Random(seed);
|
||||||
|
noises[0] = new OpenSimplexNoise(random.nextInt());
|
||||||
|
noises[1] = new OpenSimplexNoise(random.nextInt());
|
||||||
|
noiseIterations = (byte) Math.min(Math.ceil(Math.log(scale) / Math.log(2)), 5);
|
||||||
|
this.seed = (int) (seed & 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCache() {
|
||||||
|
if (chunks.size() > 127) {
|
||||||
|
chunks.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BCLBiome getBiome(double x, double z) {
|
||||||
|
BCLBiome BCLBiome = getRawBiome(x, z);
|
||||||
|
if (BCLBiome.getEdge() != null) {
|
||||||
|
float offset = scale * BCLBiome.getEdgeSize();
|
||||||
|
for (byte i = 0; i < 8; i++) {
|
||||||
|
if (getRawBiome(x + offset * EDGE_CIRCLE_X[i], z + offset * EDGE_CIRCLE_Z[i]) != BCLBiome) {
|
||||||
|
return BCLBiome.getEdge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BCLBiome;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BCLBiome getRawBiome(double x, double z) {
|
||||||
|
double px = x / scale * RAD_INNER;
|
||||||
|
double pz = z / scale;
|
||||||
|
double dx = rotateX(px, pz);
|
||||||
|
double dz = rotateZ(px, pz);
|
||||||
|
px = dx;
|
||||||
|
pz = dz;
|
||||||
|
|
||||||
|
dx = getNoise(px, pz, (byte) 0) * 0.2F;
|
||||||
|
dz = getNoise(pz, px, (byte) 1) * 0.2F;
|
||||||
|
px += dx;
|
||||||
|
pz += dz;
|
||||||
|
|
||||||
|
int cellZ = (int) Math.floor(pz);
|
||||||
|
boolean offset = (cellZ & 1) == 1;
|
||||||
|
|
||||||
|
if (offset) {
|
||||||
|
px += 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellX = (int) Math.floor(px);
|
||||||
|
|
||||||
|
float pointX = (float) (px - cellX - 0.5);
|
||||||
|
float pointZ = (float) (pz - cellZ - 0.5);
|
||||||
|
|
||||||
|
if (Math.abs(pointZ) < 0.3333F) {
|
||||||
|
return getChunkBiome(cellX, cellZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insideHexagon(0, 0, 1.1555F, pointZ * RAD_INNER, pointX)) {
|
||||||
|
return getChunkBiome(cellX, cellZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
cellX = pointX < 0 ? (offset ? cellX - 1 : cellX) : (offset ? cellX : cellX + 1);
|
||||||
|
cellZ = pointZ < 0 ? cellZ - 1 : cellZ + 1;
|
||||||
|
|
||||||
|
return getChunkBiome(cellX, cellZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BCLBiome getChunkBiome(int x, int z) {
|
||||||
|
int cx = HexBiomeChunk.scaleCoordinate(x);
|
||||||
|
int cz = HexBiomeChunk.scaleCoordinate(z);
|
||||||
|
|
||||||
|
if (((z >> 2) & 1) == 0 && HexBiomeChunk.isBorder(x)) {
|
||||||
|
x = 0;
|
||||||
|
cx += 1;
|
||||||
|
}
|
||||||
|
else if (((x >> 2) & 1) == 0 && HexBiomeChunk.isBorder(z)) {
|
||||||
|
z = 0;
|
||||||
|
cz += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
selector.setLocation(cx, cz);
|
||||||
|
HexBiomeChunk chunk = chunks.get(selector);
|
||||||
|
if (chunk == null) {
|
||||||
|
RANDOM.setSeed(MHelper.getSeed(seed, cx, cz));
|
||||||
|
chunk = new HexBiomeChunk(RANDOM, picker);
|
||||||
|
chunks.put(new Point(selector), chunk);
|
||||||
|
}
|
||||||
|
return chunk.getBiome(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean insideHexagon(float centerX, float centerZ, float radius, float x, float z) {
|
||||||
|
double dx = Math.abs(x - centerX) / radius;
|
||||||
|
double dy = Math.abs(z - centerZ) / radius;
|
||||||
|
return (dy <= COEF) && (COEF * dx + 0.25F * dy <= COEF_HALF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getNoise(double x, double z, byte state) {
|
||||||
|
double result = 0;
|
||||||
|
for (byte i = 1; i <= noiseIterations; i++) {
|
||||||
|
OpenSimplexNoise noise = noises[state];
|
||||||
|
state = (byte) ((state + 1) & 1);
|
||||||
|
result += noise.eval(x * i, z * i) / i;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double rotateX(double x, double z) {
|
||||||
|
return x * COS - z * SIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double rotateZ(double x, double z) {
|
||||||
|
return x * SIN + z * COS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
EDGE_CIRCLE_X = new float[8];
|
||||||
|
EDGE_CIRCLE_Z = new float[8];
|
||||||
|
|
||||||
|
for (byte i = 0; i < 8; i++) {
|
||||||
|
float angle = i / 4F * (float) Math.PI;
|
||||||
|
EDGE_CIRCLE_X[i] = (float) Math.sin(angle);
|
||||||
|
EDGE_CIRCLE_Z[i] = (float) Math.cos(angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,54 +1,56 @@
|
||||||
package ru.bclib.world.generator;
|
package ru.bclib.world.generator.map.square;
|
||||||
|
|
||||||
import ru.bclib.world.biomes.BCLBiome;
|
import ru.bclib.world.biomes.BCLBiome;
|
||||||
|
import ru.bclib.world.generator.BiomePicker;
|
||||||
import java.util.Random;
|
|
||||||
|
import java.util.Random;
|
||||||
public class BiomeChunk {
|
|
||||||
private static final int BIT_OFFSET = 4;
|
@Deprecated
|
||||||
protected static final int WIDTH = 1 << BIT_OFFSET;
|
public class SquareBiomeChunk {
|
||||||
private static final int SM_WIDTH = WIDTH >> 1;
|
private static final int BIT_OFFSET = 4;
|
||||||
private static final int SM_BIT_OFFSET = BIT_OFFSET >> 1;
|
protected static final int WIDTH = 1 << BIT_OFFSET;
|
||||||
private static final int MASK_OFFSET = SM_WIDTH - 1;
|
private static final int SM_WIDTH = WIDTH >> 1;
|
||||||
protected static final int MASK_WIDTH = WIDTH - 1;
|
private static final int SM_BIT_OFFSET = BIT_OFFSET >> 1;
|
||||||
|
private static final int MASK_OFFSET = SM_WIDTH - 1;
|
||||||
private static final int SM_CAPACITY = SM_WIDTH * SM_WIDTH;
|
protected static final int MASK_WIDTH = WIDTH - 1;
|
||||||
private static final int CAPACITY = WIDTH * WIDTH;
|
|
||||||
|
private static final int SM_CAPACITY = SM_WIDTH * SM_WIDTH;
|
||||||
private final BCLBiome[] biomes;
|
private static final int CAPACITY = WIDTH * WIDTH;
|
||||||
|
|
||||||
public BiomeChunk(BiomeMap map, Random random, BiomePicker picker) {
|
private final BCLBiome[] biomes;
|
||||||
BCLBiome[] PreBio = new BCLBiome[SM_CAPACITY];
|
|
||||||
biomes = new BCLBiome[CAPACITY];
|
public SquareBiomeChunk(SquareBiomeMap map, Random random, BiomePicker picker) {
|
||||||
|
BCLBiome[] PreBio = new BCLBiome[SM_CAPACITY];
|
||||||
for (int x = 0; x < SM_WIDTH; x++) {
|
biomes = new BCLBiome[CAPACITY];
|
||||||
int offset = x << SM_BIT_OFFSET;
|
|
||||||
for (int z = 0; z < SM_WIDTH; z++) {
|
for (int x = 0; x < SM_WIDTH; x++) {
|
||||||
PreBio[offset | z] = picker.getBiome(random);
|
int offset = x << SM_BIT_OFFSET;
|
||||||
}
|
for (int z = 0; z < SM_WIDTH; z++) {
|
||||||
}
|
PreBio[offset | z] = picker.getBiome(random);
|
||||||
|
}
|
||||||
for (int x = 0; x < WIDTH; x++) {
|
}
|
||||||
int offset = x << BIT_OFFSET;
|
|
||||||
for (int z = 0; z < WIDTH; z++) {
|
for (int x = 0; x < WIDTH; x++) {
|
||||||
biomes[offset | z] = PreBio[getSmIndex(offsetXZ(x, random), offsetXZ(z, random))].getSubBiome(random);
|
int offset = x << BIT_OFFSET;
|
||||||
}
|
for (int z = 0; z < WIDTH; z++) {
|
||||||
}
|
biomes[offset | z] = PreBio[getSmIndex(offsetXZ(x, random), offsetXZ(z, random))].getSubBiome(random);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public BCLBiome getBiome(int x, int z) {
|
}
|
||||||
return biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)];
|
|
||||||
}
|
public BCLBiome getBiome(int x, int z) {
|
||||||
|
return biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)];
|
||||||
private int offsetXZ(int x, Random random) {
|
}
|
||||||
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
|
|
||||||
}
|
private int offsetXZ(int x, Random random) {
|
||||||
|
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
|
||||||
private int getIndex(int x, int z) {
|
}
|
||||||
return x << BIT_OFFSET | z;
|
|
||||||
}
|
private int getIndex(int x, int z) {
|
||||||
|
return x << BIT_OFFSET | z;
|
||||||
private int getSmIndex(int x, int z) {
|
}
|
||||||
return x << SM_BIT_OFFSET | z;
|
|
||||||
}
|
private int getSmIndex(int x, int z) {
|
||||||
}
|
return x << SM_BIT_OFFSET | z;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,113 +1,115 @@
|
||||||
package ru.bclib.world.generator;
|
package ru.bclib.world.generator.map.square;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
||||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||||
import ru.bclib.noise.OpenSimplexNoise;
|
import ru.bclib.noise.OpenSimplexNoise;
|
||||||
import ru.bclib.util.MHelper;
|
import ru.bclib.util.MHelper;
|
||||||
import ru.bclib.world.biomes.BCLBiome;
|
import ru.bclib.world.biomes.BCLBiome;
|
||||||
|
import ru.bclib.world.generator.BiomePicker;
|
||||||
import java.util.Map;
|
|
||||||
|
import java.util.Map;
|
||||||
public class BiomeMap {
|
|
||||||
private final WorldgenRandom RANDOM;
|
@Deprecated
|
||||||
|
public class SquareBiomeMap {
|
||||||
private final Map<ChunkPos, BiomeChunk> maps = Maps.newHashMap();
|
private final WorldgenRandom RANDOM;
|
||||||
private final int size;
|
|
||||||
private final int sizeXZ;
|
private final Map<ChunkPos, SquareBiomeChunk> maps = Maps.newHashMap();
|
||||||
private final int depth;
|
private final int size;
|
||||||
private final OpenSimplexNoise noiseX;
|
private final int sizeXZ;
|
||||||
private final OpenSimplexNoise noiseZ;
|
private final int depth;
|
||||||
private final BiomePicker picker;
|
private final OpenSimplexNoise noiseX;
|
||||||
private final long seed;
|
private final OpenSimplexNoise noiseZ;
|
||||||
|
private final BiomePicker picker;
|
||||||
public BiomeMap(long seed, int size, BiomePicker picker) {
|
private final long seed;
|
||||||
maps.clear();
|
|
||||||
RANDOM = new WorldgenRandom(new LegacyRandomSource(seed));
|
public SquareBiomeMap(long seed, int size, BiomePicker picker) {
|
||||||
noiseX = new OpenSimplexNoise(RANDOM.nextLong());
|
maps.clear();
|
||||||
noiseZ = new OpenSimplexNoise(RANDOM.nextLong());
|
RANDOM = new WorldgenRandom(new LegacyRandomSource(seed));
|
||||||
this.sizeXZ = size;
|
noiseX = new OpenSimplexNoise(RANDOM.nextLong());
|
||||||
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
|
noiseZ = new OpenSimplexNoise(RANDOM.nextLong());
|
||||||
this.size = 1 << depth;
|
this.sizeXZ = size;
|
||||||
this.picker = picker;
|
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
|
||||||
this.seed = seed;
|
this.size = 1 << depth;
|
||||||
}
|
this.picker = picker;
|
||||||
|
this.seed = seed;
|
||||||
public long getSeed() {
|
}
|
||||||
return seed;
|
|
||||||
}
|
public long getSeed() {
|
||||||
|
return seed;
|
||||||
public void clearCache() {
|
}
|
||||||
if (maps.size() > 32) {
|
|
||||||
maps.clear();
|
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;
|
private BCLBiome getRawBiome(int bx, int bz) {
|
||||||
double nx = x;
|
double x = (double) bx * size / sizeXZ;
|
||||||
double nz = z;
|
double z = (double) bz * size / sizeXZ;
|
||||||
|
double nx = x;
|
||||||
double px = bx * 0.2;
|
double nz = z;
|
||||||
double pz = bz * 0.2;
|
|
||||||
|
double px = bx * 0.2;
|
||||||
for (int i = 0; i < depth; i++) {
|
double pz = bz * 0.2;
|
||||||
nx = (x + noiseX.eval(px, pz)) / 2F;
|
|
||||||
nz = (z + noiseZ.eval(px, pz)) / 2F;
|
for (int i = 0; i < depth; i++) {
|
||||||
|
nx = (x + noiseX.eval(px, pz)) / 2F;
|
||||||
x = nx;
|
nz = (z + noiseZ.eval(px, pz)) / 2F;
|
||||||
z = nz;
|
|
||||||
|
x = nx;
|
||||||
px = px / 2 + i;
|
z = nz;
|
||||||
pz = pz / 2 + i;
|
|
||||||
}
|
px = px / 2 + i;
|
||||||
|
pz = pz / 2 + i;
|
||||||
bx = MHelper.floor(x);
|
}
|
||||||
bz = MHelper.floor(z);
|
|
||||||
if ((bx & BiomeChunk.MASK_WIDTH) == BiomeChunk.MASK_WIDTH) {
|
bx = MHelper.floor(x);
|
||||||
x += (bz / 2) & 1;
|
bz = MHelper.floor(z);
|
||||||
}
|
if ((bx & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.MASK_WIDTH) {
|
||||||
if ((bz & BiomeChunk.MASK_WIDTH) == BiomeChunk.MASK_WIDTH) {
|
x += (bz / 2) & 1;
|
||||||
z += (bx / 2) & 1;
|
}
|
||||||
}
|
if ((bz & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.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) {
|
ChunkPos cpos = new ChunkPos(MHelper.floor(x / SquareBiomeChunk.WIDTH), MHelper.floor(z / SquareBiomeChunk.WIDTH));
|
||||||
RANDOM.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
|
SquareBiomeChunk chunk = maps.get(cpos);
|
||||||
chunk = new BiomeChunk(this, RANDOM, picker);
|
if (chunk == null) {
|
||||||
maps.put(cpos, chunk);
|
RANDOM.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
|
||||||
}
|
chunk = new SquareBiomeChunk(this, RANDOM, picker);
|
||||||
|
maps.put(cpos, chunk);
|
||||||
return chunk.getBiome(MHelper.floor(x), MHelper.floor(z));
|
}
|
||||||
}
|
|
||||||
|
return chunk.getBiome(MHelper.floor(x), MHelper.floor(z));
|
||||||
public BCLBiome getBiome(int x, int z) {
|
}
|
||||||
BCLBiome biome = getRawBiome(x, z);
|
|
||||||
|
public BCLBiome getBiome(int x, int z) {
|
||||||
if (biome.getEdge() != null || (biome.getParentBiome() != null && biome.getParentBiome().getEdge() != null)) {
|
BCLBiome biome = getRawBiome(x, z);
|
||||||
BCLBiome search = biome;
|
|
||||||
if (biome.getParentBiome() != null) {
|
if (biome.getEdge() != null || (biome.getParentBiome() != null && biome.getParentBiome().getEdge() != null)) {
|
||||||
search = biome.getParentBiome();
|
BCLBiome search = biome;
|
||||||
}
|
if (biome.getParentBiome() != null) {
|
||||||
int d = (int) Math.ceil(search.getEdgeSize() / 4F) << 2;
|
search = biome.getParentBiome();
|
||||||
|
}
|
||||||
boolean edge = !search.isSame(getRawBiome(x + d, z));
|
int d = (int) Math.ceil(search.getEdgeSize() / 4F) << 2;
|
||||||
edge = edge || !search.isSame(getRawBiome(x - d, z));
|
|
||||||
edge = edge || !search.isSame(getRawBiome(x, z + d));
|
boolean edge = !search.isSame(getRawBiome(x + d, z));
|
||||||
edge = edge || !search.isSame(getRawBiome(x, z - d));
|
edge = edge || !search.isSame(getRawBiome(x - d, z));
|
||||||
edge = edge || !search.isSame(getRawBiome(x - 1, z - 1));
|
edge = edge || !search.isSame(getRawBiome(x, z + d));
|
||||||
edge = edge || !search.isSame(getRawBiome(x - 1, z + 1));
|
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));
|
||||||
|
edge = edge || !search.isSame(getRawBiome(x + 1, z - 1));
|
||||||
if (edge) {
|
edge = edge || !search.isSame(getRawBiome(x + 1, z + 1));
|
||||||
biome = search.getEdge();
|
|
||||||
}
|
if (edge) {
|
||||||
}
|
biome = search.getEdge();
|
||||||
|
}
|
||||||
return biome;
|
}
|
||||||
}
|
|
||||||
}
|
return biome;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue