Removed old End Caves (temporary), added new Caves and Cave API (WIP)

This commit is contained in:
paulevsGitch 2021-03-09 02:40:26 +03:00
parent 2135fe50b5
commit 231794363b
14 changed files with 384 additions and 28 deletions

View file

@ -67,13 +67,19 @@ public class BiomeDefinition {
private final Identifier id;
private float genChance = 1F;
private boolean hasCaves = true;
private boolean isCaveBiome = false;
private ConfiguredSurfaceBuilder<?> surface;
public BiomeDefinition(String name) {
this.id = BetterEnd.makeID(name);
}
public BiomeDefinition setCaveBiome() {
isCaveBiome = true;
return this;
}
public BiomeDefinition setSurface(Block block) {
setSurface(SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(
block.getDefaultState(),
@ -249,7 +255,7 @@ public class BiomeDefinition {
return new Biome.Builder()
.precipitation(Precipitation.NONE)
.category(Category.THEEND)
.category(isCaveBiome ? Category.NONE : Category.THEEND)
.depth(0.1F)
.scale(0.2F)
.temperature(2.0F)

View file

@ -0,0 +1,18 @@
package ru.betterend.world.biome;
import ru.betterend.registry.EndBlocks;
import ru.betterend.registry.EndParticles;
import ru.betterend.registry.EndSounds;
public class EmptyEndCaveBiome extends EndCaveBiome {
public EmptyEndCaveBiome() {
super(new BiomeDefinition("empty_end_cave")
.setFogColor(255, 184, 71)
.setFogDensity(2.0F)
.setPlantsColor(219, 115, 38)
.setWaterAndFogColor(145, 108, 72)
.setMusic(EndSounds.MUSIC_FOREST)
.setParticles(EndParticles.AMBER_SPHERE, 0.001F)
.setSurface(EndBlocks.AMBER_MOSS));
}
}

View file

@ -190,8 +190,7 @@ public class EndBiome {
if (edge != null) {
edge.updateActualBiomes(biomeRegistry);
}
Biome biome = biomeRegistry.get(mcID);
this.actualBiome = biome;
this.actualBiome = biomeRegistry.get(mcID);
}
@Override

View file

@ -0,0 +1,33 @@
package ru.betterend.world.biome;
import java.util.List;
import java.util.Random;
import com.google.common.collect.Lists;
import net.minecraft.world.gen.feature.Feature;
public class EndCaveBiome extends EndBiome {
private List<Feature<?>> floorFeatures = Lists.newArrayList();
private List<Feature<?>> ceilFeatures = Lists.newArrayList();
public EndCaveBiome(BiomeDefinition definition) {
super(definition.setCaveBiome());
}
public void addFloorFeature(Feature<?> feature) {
floorFeatures.add(feature);
}
public void addCeilFeature(Feature<?> feature) {
ceilFeatures.add(feature);
}
public Feature<?> getFloorFeature(Random random) {
return floorFeatures.isEmpty() ? null : floorFeatures.get(random.nextInt(floorFeatures.size()));
}
public Feature<?> getCeilFeature(Random random) {
return ceilFeatures.isEmpty() ? null : ceilFeatures.get(random.nextInt(ceilFeatures.size()));
}
}

View file

@ -32,6 +32,7 @@ import ru.betterend.util.sdf.primitive.SDFSphere;
import ru.betterend.world.features.DefaultFeature;
import ru.betterend.world.generator.GeneratorOptions;
@Deprecated
public class RoundCaveFeature extends DefaultFeature {
private static final BlockState CAVE_AIR = Blocks.CAVE_AIR.getDefaultState();

View file

@ -0,0 +1,134 @@
package ru.betterend.world.features.terrain.caves;
import java.util.Random;
import java.util.Set;
import com.google.common.collect.Sets;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.Mutable;
import net.minecraft.world.Heightmap;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import ru.betterend.interfaces.IBiomeArray;
import ru.betterend.registry.EndBiomes;
import ru.betterend.registry.EndTags;
import ru.betterend.util.BlocksHelper;
import ru.betterend.util.MHelper;
import ru.betterend.world.biome.EndCaveBiome;
import ru.betterend.world.features.DefaultFeature;
import ru.betterend.world.generator.GeneratorOptions;
public abstract class EndCaveFeature extends DefaultFeature {
protected static final BlockState CAVE_AIR = Blocks.CAVE_AIR.getDefaultState();
protected static final BlockState END_STONE = Blocks.END_STONE.getDefaultState();
protected static final BlockState WATER = Blocks.WATER.getDefaultState();
@Override
public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) {
if (!(GeneratorOptions.useNewGenerator() && GeneratorOptions.noRingVoid()) || pos.getX() * pos.getX() + pos.getZ() * pos.getZ() <= 22500) {
return false;
}
int radius = MHelper.randRange(10, 30, random);
BlockPos center = findPos(world, pos, radius, random);
if (center == null) {
return false;
}
EndCaveBiome biome = EndBiomes.getCaveBiome(random);
Set<BlockPos> caveBlocks = generate(world, center, radius, random);
if (biome != null && !caveBlocks.isEmpty()) {
setBiomes(world, biome, caveBlocks);
Set<BlockPos> floorPositions = Sets.newHashSet();
Set<BlockPos> ceilPositions = Sets.newHashSet();
Mutable mut = new Mutable();
caveBlocks.forEach((bpos) -> {
mut.set(bpos);
if (world.getBlockState(mut).getMaterial().isReplaceable()) {
mut.setY(bpos.getY() - 1);
if (world.getBlockState(mut).isIn(EndTags.GEN_TERRAIN)) {
floorPositions.add(mut.toImmutable());
}
mut.setY(bpos.getY() + 1);
if (world.getBlockState(mut).isIn(EndTags.GEN_TERRAIN)) {
ceilPositions.add(mut.toImmutable());
}
}
});
BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceConfig().getTopMaterial();
placeFloor(world, biome, floorPositions, random, surfaceBlock);
placeCeil(world, biome, ceilPositions, random);
}
fixBlocks(world, center, radius);
return true;
}
protected abstract Set<BlockPos> generate(StructureWorldAccess world, BlockPos center, int radius, Random random);
protected void placeFloor(StructureWorldAccess world, EndCaveBiome biome, Set<BlockPos> floorPositions, Random random, BlockState surfaceBlock) {
floorPositions.forEach((pos) -> {
BlocksHelper.setWithoutUpdate(world, pos, surfaceBlock);
});
}
protected void placeCeil(StructureWorldAccess world, EndCaveBiome biome, Set<BlockPos> ceilPositions, Random random) {
}
protected void setBiomes(StructureWorldAccess world, EndCaveBiome biome, Set<BlockPos> blocks) {
blocks.forEach((pos) -> setBiome(world, pos, biome));
}
private void setBiome(StructureWorldAccess world, BlockPos pos, EndCaveBiome biome) {
IBiomeArray array = (IBiomeArray) world.getChunk(pos).getBiomeArray();
if (array != null) {
array.setBiome(biome.getActualBiome(), pos);
}
}
private BlockPos findPos(StructureWorldAccess world, BlockPos pos, int radius, Random random) {
int top = world.getTopY(Heightmap.Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ());
Mutable bpos = new Mutable();
bpos.setX(pos.getX());
bpos.setZ(pos.getZ());
bpos.setY(top - 1);
BlockState state = world.getBlockState(bpos);
while (!state.isIn(EndTags.GEN_TERRAIN) && bpos.getY() > 5) {
bpos.setY(bpos.getY() - 1);
state = world.getBlockState(bpos);
}
if (bpos.getY() < 10) {
return null;
}
top = (int) (bpos.getY() - (radius * 1.3F + 5));
while (state.isIn(EndTags.GEN_TERRAIN) || !state.getFluidState().isEmpty() && bpos.getY() > 5) {
bpos.setY(bpos.getY() - 1);
state = world.getBlockState(bpos);
}
int bottom = (int) (bpos.getY() + radius * 1.3F + 5);
if (top <= bottom) {
return null;
}
return new BlockPos(pos.getX(), MHelper.randRange(bottom, top, random), pos.getZ());
}
private void fixBlocks(StructureWorldAccess world, BlockPos pos, int radius) {
int x1 = pos.getX() - radius - 5;
int y1 = pos.getY() - radius - 5;
int z1 = pos.getZ() - radius - 5;
int x2 = pos.getX() + radius + 5;
int y2 = pos.getY() + radius + 5;
int z2 = pos.getZ() + radius + 5;
BlocksHelper.fixBlocks(world, new BlockPos(x1, y1, z1), new BlockPos(x2, y2, z2));
}
}

View file

@ -0,0 +1,85 @@
package ru.betterend.world.features.terrain.caves;
import java.util.Random;
import java.util.Set;
import com.google.common.collect.Sets;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.Mutable;
import net.minecraft.world.StructureWorldAccess;
import ru.betterend.noise.OpenSimplexNoise;
import ru.betterend.registry.EndTags;
import ru.betterend.util.BlocksHelper;
import ru.betterend.util.MHelper;
public class RoundCaveFeature extends EndCaveFeature {
@Override
protected Set<BlockPos> generate(StructureWorldAccess world, BlockPos center, int radius, Random random) {
OpenSimplexNoise noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ()));
int x1 = center.getX() - radius - 5;
int z1 = center.getZ() - radius - 5;
int x2 = center.getX() + radius + 5;
int z2 = center.getZ() + radius + 5;
int y1 = MHelper.floor(center.getY() - (radius + 5) / 1.6);
int y2 = MHelper.floor(center.getY() + (radius + 5) / 1.6);
double hr = radius * 0.75;
double nr = radius * 0.25;
BlockState state;
Mutable bpos = new Mutable();
Set<BlockPos> blocks = Sets.newHashSet();
for (int x = x1; x <= x2; x++) {
int xsq = x - center.getX();
xsq *= xsq;
bpos.setX(x);
for (int z = z1; z <= z2; z++) {
int zsq = z - center.getZ();
zsq *= zsq;
bpos.setZ(z);
for (int y = y1; y <= y2; y++) {
int ysq = y - center.getY();
ysq *= 1.6;
ysq *= ysq;
bpos.setY(y);
double r = noise.eval(x * 0.1, y * 0.1, z * 0.1) * nr + hr;
//double r2 = r + 5;
double dist = xsq + ysq + zsq;
if (dist < r * r) {
state = world.getBlockState(bpos);
if (isReplaceable(state)) {
BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR);
blocks.add(bpos.toImmutable());
while (state.getMaterial().equals(Material.LEAVES)) {
BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR);
bpos.setY(bpos.getY() + 1);
state = world.getBlockState(bpos);
}
bpos.setY(y - 1);
while (state.getMaterial().equals(Material.LEAVES)) {
BlocksHelper.setWithoutUpdate(world, bpos, CAVE_AIR);
bpos.setY(bpos.getY() - 1);
state = world.getBlockState(bpos);
}
}
}
}
}
}
return blocks;
}
private boolean isReplaceable(BlockState state) {
return state.isIn(EndTags.GEN_TERRAIN)
|| state.getMaterial().isReplaceable()
|| state.getMaterial().equals(Material.PLANT)
|| state.getMaterial().equals(Material.LEAVES);
}
}

View file

@ -10,7 +10,6 @@ import net.minecraft.util.math.noise.SimplexNoiseSampler;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryLookupCodec;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biome.Category;
import net.minecraft.world.biome.BiomeKeys;
import net.minecraft.world.biome.source.BiomeSource;
import net.minecraft.world.biome.source.TheEndBiomeSource;
@ -61,7 +60,7 @@ public class BetterEndBiomeSource extends BiomeSource {
private static List<Biome> getBiomes(Registry<Biome> biomeRegistry) {
List<Biome> list = Lists.newArrayList();
biomeRegistry.forEach((biome) -> {
if (biome.getCategory() == Category.THEEND) {
if (EndBiomes.hasBiome(biomeRegistry.getId(biome))) {
list.add(biome);
}
});

View file

@ -32,12 +32,13 @@ public class BiomePicker {
public void clearMutables() {
maxChance = maxChanceUnmutable;
for (int i = biomes.size() - 1; i >= biomeCount; i--)
for (int i = biomes.size() - 1; i >= biomeCount; i--) {
biomes.remove(i);
}
}
public EndBiome getBiome(Random random) {
return tree.getBiome(random.nextFloat() * maxChance);
return biomes.isEmpty() ? null : tree.getBiome(random.nextFloat() * maxChance);
}
public List<EndBiome> getBiomes() {
@ -59,6 +60,9 @@ public class BiomePicker {
}
public void rebuild() {
if (biomes.isEmpty()) {
return;
}
maxChance = maxChanceUnmutable;
for (int i = biomeCount; i < biomes.size(); i++) {
maxChance = biomes.get(i).mutateGenChance(maxChance);