Vertical biomes distribution prototype

This commit is contained in:
paulevsGitch 2021-12-11 19:33:53 +03:00
parent 330530de73
commit 6cb75406cb
17 changed files with 213 additions and 65 deletions

View file

@ -11,7 +11,7 @@ loader_version= 0.12.9
fabric_version = 0.44.0+1.18
# Mod Properties
mod_version = 1.0.3
mod_version = 1.1.0
maven_group = ru.bclib
archives_base_name = bclib

View file

@ -1,7 +1,6 @@
package ru.bclib;
import net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.NotNull;
import ru.bclib.api.datafixer.DataFixerAPI;
import ru.bclib.api.datafixer.ForcedLevelPatch;
import ru.bclib.api.datafixer.MigrationProfile;

View file

@ -1,19 +1,5 @@
package ru.bclib.api.biomes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
@ -21,7 +7,6 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
@ -59,6 +44,7 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;
import ru.bclib.BCLib;
import ru.bclib.config.Configs;
import ru.bclib.entity.BCLEntityWrapper;
@ -76,6 +62,18 @@ import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.generator.BiomePicker;
import ru.bclib.world.structures.BCLStructureFeature;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class BiomeAPI {
/**
* Empty biome used as default value if requested biome doesn't exist or linked. Shouldn't be registered anywhere to prevent bugs.

View file

@ -0,0 +1,9 @@
package ru.bclib.interfaces;
import ru.bclib.world.biomes.BCLBiome;
public interface BiomeChunk {
void setBiome(int x, int z, BCLBiome biome);
BCLBiome getBiome(int x, int z);
int getSide();
}

View file

@ -3,7 +3,8 @@ package ru.bclib.interfaces;
import ru.bclib.world.biomes.BCLBiome;
public interface BiomeMap {
void clearCache();
void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor);
BiomeChunk getChunk(int cx, int cz, boolean update);
BCLBiome getBiome(double x, double y, double z);
void clearCache();
}

View file

@ -1,16 +1,6 @@
package ru.bclib.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Random;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.google.common.collect.Sets;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
@ -32,6 +22,15 @@ import net.minecraft.world.phys.Vec3;
import ru.bclib.api.TagAPI;
import ru.bclib.api.biomes.BiomeAPI;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Random;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class StructureHelper {
private static final Direction[] DIR = BlocksHelper.makeHorizontal();

View file

@ -36,6 +36,7 @@ public class BCLBiome {
private float fogDensity = 1.0F;
private float genChance = 1.0F;
private float edgeSize = 0.0F;
private boolean vertical;
/**
* Create wrapper for existing biome using its {@link ResourceLocation} identifier.
@ -291,6 +292,32 @@ public class BCLBiome {
return terrainHeight;
}
/**
* Set biome vertical distribution (for tall Nether only).
* @return same {@link BCLBiome}.
*/
public BCLBiome setVertical() {
return setVertical(true);
}
/**
* Set biome vertical distribution (for tall Nether only).
* @param vertical {@code boolean} value.
* @return same {@link BCLBiome}.
*/
public BCLBiome setVertical(boolean vertical) {
this.vertical = vertical;
return this;
}
/**
* Checks if biome is vertical, for tall Nether only (or for custom generators).
* @return is biome vertical or not.
*/
public boolean isVertical() {
return vertical;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {

View file

@ -1,8 +1,5 @@
package ru.bclib.world.features;
import java.util.List;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Mirror;
@ -12,6 +9,9 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlac
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import ru.bclib.util.StructureHelper;
import java.util.List;
import java.util.Random;
public class ListFeature extends NBTStructureFeature {
private final List<StructureInfo> list;
private StructureInfo selected;

View file

@ -1,9 +1,5 @@
package ru.bclib.world.features;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
@ -27,6 +23,10 @@ import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.util.BlocksHelper;
import ru.bclib.world.processors.DestructionStructureProcessor;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
public abstract class NBTStructureFeature extends DefaultFeature {
private final BlockState defaultBlock;
public NBTStructureFeature(BlockState defaultBlock){

View file

@ -1,12 +1,12 @@
package ru.bclib.world.generator;
import java.util.List;
import net.minecraft.core.Registry;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import ru.bclib.api.biomes.BiomeAPI;
import java.util.List;
public abstract class BCLBiomeSource extends BiomeSource {
protected final Registry<Biome> biomeRegistry;
protected final long seed;

View file

@ -1,9 +1,5 @@
package ru.bclib.world.generator;
import java.awt.Point;
import java.util.List;
import java.util.function.Function;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Registry;
@ -28,6 +24,10 @@ import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.map.hex.HexBiomeMap;
import ru.bclib.world.generator.map.square.SquareBiomeMap;
import java.awt.Point;
import java.util.List;
import java.util.function.Function;
public class BCLibEndBiomeSource extends BCLBiomeSource {
public static final Codec<BCLibEndBiomeSource> CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter((theEndBiomeSource) -> {

View file

@ -1,7 +1,5 @@
package ru.bclib.world.generator;
import java.util.List;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Registry;
@ -22,6 +20,8 @@ import ru.bclib.world.generator.map.MapStack;
import ru.bclib.world.generator.map.hex.HexBiomeMap;
import ru.bclib.world.generator.map.square.SquareBiomeMap;
import java.util.List;
public class BCLibNetherBiomeSource extends BCLBiomeSource {
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter((theEndBiomeSource) -> {

View file

@ -2,7 +2,9 @@ package ru.bclib.world.generator.map;
import net.minecraft.util.Mth;
import org.apache.commons.lang3.function.TriFunction;
import ru.bclib.interfaces.BiomeChunk;
import ru.bclib.interfaces.BiomeMap;
import ru.bclib.interfaces.TriConsumer;
import ru.bclib.noise.OpenSimplexNoise;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.BiomePicker;
@ -29,6 +31,7 @@ public class MapStack implements BiomeMap {
Random random = new Random(seed);
for (int i = 0; i < mapCount; i++) {
maps[i] = mapConstructor.apply(random.nextLong(), size, picker);
maps[i].setChunkProcessor(this::onChunkCreation);
}
noise = new OpenSimplexNoise(random.nextInt());
}
@ -40,6 +43,14 @@ public class MapStack implements BiomeMap {
}
}
@Override
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {}
@Override
public BiomeChunk getChunk(int cx, int cz, boolean update) {
return null;
}
@Override
public BCLBiome getBiome(double x, double y, double z) {
int mapIndex;
@ -57,4 +68,39 @@ public class MapStack implements BiomeMap {
return maps[mapIndex].getBiome(x, y, z);
}
private void onChunkCreation(int cx, int cz, int side) {
System.out.println("Creation " + cx + " " + cz);
BCLBiome[][] biomeMap = new BCLBiome[side][side];
BiomeChunk[] chunks = new BiomeChunk[maps.length];
boolean isNoEmpty = false;
for (int i = 0; i < maps.length; i++) {
chunks[i] = maps[i].getChunk(cx, cz, false);
for (int x = 0; x < side; x++) {
for (int z = 0; z < side; z++) {
if (biomeMap[x][z] == null) {
BCLBiome biome = chunks[i].getBiome(x, z);
if (biome.isVertical()) {
biomeMap[x][z] = biome;
isNoEmpty = true;
}
}
}
}
}
if (isNoEmpty) {
for (int i = 0; i < maps.length; i++) {
for (int x = 0; x < side; x++) {
for (int z = 0; z < side; z++) {
if (biomeMap[x][z] != null) {
chunks[i].setBiome(x, z, biomeMap[x][z]);
}
}
}
}
}
}
}

View file

@ -1,12 +1,13 @@
package ru.bclib.world.generator.map.hex;
import ru.bclib.interfaces.BiomeChunk;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.BiomePicker;
import java.util.Arrays;
import java.util.Random;
public class HexBiomeChunk {
public class HexBiomeChunk implements BiomeChunk {
private static final short SIDE = 32;
private static final byte SIDE_PRE = 4;
private static final short SIZE = SIDE * SIDE;
@ -104,10 +105,21 @@ public class HexBiomeChunk {
return (short) ((short) x << SIDE_OFFSET | z);
}
@Override
public BCLBiome getBiome(int x, int z) {
return biomes[getIndex(wrap(x), wrap(z))];
}
@Override
public void setBiome(int x, int z, BCLBiome biome) {
biomes[getIndex(wrap(x), wrap(z))] = biome;
}
@Override
public int getSide() {
return SIDE;
}
public static int scaleCoordinate(int value) {
return value >> SIDE_OFFSET;
}

View file

@ -1,6 +1,8 @@
package ru.bclib.world.generator.map.hex;
import ru.bclib.interfaces.BiomeChunk;
import ru.bclib.interfaces.BiomeMap;
import ru.bclib.interfaces.TriConsumer;
import ru.bclib.noise.OpenSimplexNoise;
import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome;
@ -25,6 +27,7 @@ public class HexBiomeMap implements BiomeMap {
private final BiomePicker picker;
private final OpenSimplexNoise[] noises = new OpenSimplexNoise[2];
private TriConsumer<Integer, Integer, Integer> processor;
private final byte noiseIterations;
private final float scale;
private final int seed;
@ -71,6 +74,35 @@ public class HexBiomeMap implements BiomeMap {
return biome;
}
@Override
public BiomeChunk getChunk(int cx, int cz, boolean update) {
HexBiomeChunk chunk;
synchronized (selector) {
selector.setLocation(cx, cz);
chunk = chunks.get(selector);
}
if (chunk == null) {
synchronized (RANDOM) {
RANDOM.setSeed(MHelper.getSeed(seed, cx, cz));
chunk = new HexBiomeChunk(RANDOM, picker);
}
chunks.put(new Point(cx, cz), chunk);
if (update && processor != null) {
processor.accept(cx, cz, chunk.getSide());
}
}
return chunk;
}
@Override
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
this.processor = processor;
}
private BCLBiome getRawBiome(double x, double z) {
double px = x / scale * RAD_INNER;
double pz = z / scale;
@ -123,21 +155,7 @@ public class HexBiomeMap implements BiomeMap {
cz += 1;
}
HexBiomeChunk chunk;
synchronized (selector) {
selector.setLocation(cx, cz);
chunk = chunks.get(selector);
}
if (chunk == null) {
synchronized (RANDOM) {
RANDOM.setSeed(MHelper.getSeed(seed, cx, cz));
chunk = new HexBiomeChunk(RANDOM, picker);
}
chunks.put(new Point(cx, cz), chunk);
}
return chunk.getBiome(x, z);
return getChunk(cx, cz, true).getBiome(x, z);
}
private boolean insideHexagon(float centerX, float centerZ, float radius, float x, float z) {

View file

@ -1,11 +1,12 @@
package ru.bclib.world.generator.map.square;
import ru.bclib.interfaces.BiomeChunk;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.BiomePicker;
import java.util.Random;
public class SquareBiomeChunk {
public class SquareBiomeChunk implements BiomeChunk {
private static final int BIT_OFFSET = 4;
protected static final int WIDTH = 1 << BIT_OFFSET;
private static final int SM_WIDTH = WIDTH >> 1;
@ -37,10 +38,21 @@ public class SquareBiomeChunk {
}
}
@Override
public BCLBiome getBiome(int x, int z) {
return biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)];
}
@Override
public void setBiome(int x, int z, BCLBiome biome) {
biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)] = biome;
}
@Override
public int getSide() {
return WIDTH;
}
private int offsetXZ(int x, Random random) {
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
}

View file

@ -4,7 +4,9 @@ import com.google.common.collect.Maps;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import ru.bclib.interfaces.BiomeChunk;
import ru.bclib.interfaces.BiomeMap;
import ru.bclib.interfaces.TriConsumer;
import ru.bclib.noise.OpenSimplexNoise;
import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome;
@ -23,6 +25,8 @@ public class SquareBiomeMap implements BiomeMap {
private final int depth;
private final int size;
private TriConsumer<Integer, Integer, Integer> processor;
public SquareBiomeMap(long seed, int size, BiomePicker picker) {
maps.clear();
random = new WorldgenRandom(new LegacyRandomSource(seed));
@ -69,18 +73,40 @@ public class SquareBiomeMap implements BiomeMap {
return biome;
}
@Override
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
this.processor = processor;
}
@Override
public BiomeChunk getChunk(int cx, int cz, boolean update) {
ChunkPos cpos = new ChunkPos(cx, cz);
SquareBiomeChunk chunk = maps.get(cpos);
if (chunk == null) {
synchronized (random) {
random.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
chunk = new SquareBiomeChunk(random, picker);
}
maps.put(cpos, chunk);
if (update && processor != null) {
processor.accept(cx, cz, chunk.getSide());
}
}
return chunk;
}
private BCLBiome getRawBiome(double bx, double bz) {
double x = bx * size / sizeXZ;
double z = 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;
double nx = (x + noiseX.eval(px, pz)) / 2F;
double nz = (z + noiseZ.eval(px, pz)) / 2F;
x = nx;
z = nz;
@ -91,6 +117,7 @@ public class SquareBiomeMap implements BiomeMap {
int ix = MHelper.floor(x);
int iz = MHelper.floor(z);
if ((ix & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.MASK_WIDTH) {
x += (iz / 2) & 1;
}