Mountains

This commit is contained in:
paulevsGitch 2020-10-07 04:48:49 +03:00
parent 20bb6379bf
commit 466dd6604d
10 changed files with 198 additions and 39 deletions

View file

@ -1,11 +1,17 @@
package ru.betterend.mixin.common;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.DefaultBiomeCreator;
import net.minecraft.world.biome.GenerationSettings;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.feature.ConfiguredFeatures;
import net.minecraft.world.gen.feature.ConfiguredStructureFeatures;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilders;
import ru.betterend.registry.DefaultBiomeFeatureRegistry;
@Mixin(DefaultBiomeCreator.class)
public class DefaultBiomeCreatorMixin {
@ -14,7 +20,7 @@ public class DefaultBiomeCreatorMixin {
return null;
};
/*@Overwrite
@Overwrite
public static Biome createEndHighlands() {
GenerationSettings.Builder builder = (new GenerationSettings.Builder())
.surfaceBuilder(ConfiguredSurfaceBuilders.END).structureFeature(ConfiguredStructureFeatures.END_CITY)
@ -22,5 +28,5 @@ public class DefaultBiomeCreatorMixin {
.feature(GenerationStep.Feature.VEGETAL_DECORATION, ConfiguredFeatures.CHORUS_PLANT)
.structureFeature(DefaultBiomeFeatureRegistry.MOUNTAINS.getFeatureConfigured());
return composeEndSpawnSettings(builder);
}*/
}
}

View file

@ -5,6 +5,5 @@ import ru.betterend.world.structures.EndStructureFeature;
import ru.betterend.world.structures.features.StructureMountain;
public class DefaultBiomeFeatureRegistry {
//public static final EndFeature MOUNTAINS = EndFeature.makeChunkFeature("mountains", new MountainFeature());
public static final EndStructureFeature MOUNTAINS = new EndStructureFeature("mountains", new StructureMountain(), Feature.RAW_GENERATION, 6, 3);
public static final EndStructureFeature MOUNTAINS = new EndStructureFeature("mountains", new StructureMountain(), Feature.RAW_GENERATION, 3, 2);
}

View file

@ -6,10 +6,12 @@ import net.minecraft.world.gen.GenerationStep.Feature;
import ru.betterend.BetterEnd;
import ru.betterend.world.structures.EndStructureFeature;
import ru.betterend.world.structures.features.StructureGiantMossyGlowshroom;
import ru.betterend.world.structures.piece.MountainPiece;
import ru.betterend.world.structures.piece.VoxelPiece;
public class StructureRegistry {
public static final StructurePieceType VOXEL_PIECE = register("voxel", VoxelPiece::new);
public static final StructurePieceType MOUNTAIN_PIECE = register("mountain_piece", MountainPiece::new);
public static final EndStructureFeature GIANT_MOSSY_GLOWSHROOM = new EndStructureFeature("giant_mossy_glowshroom", new StructureGiantMossyGlowshroom(), Feature.SURFACE_STRUCTURES, 16, 8);

View file

@ -100,4 +100,16 @@ public class MHelper {
public static float dot(float x1, float y1, float x2, float y2) {
return x1 * x2 + y1 * y2;
}
public static int getSeed(int seed, int x, int y) {
int h = seed + x * 374761393 + y * 668265263;
h = (h ^ (h >> 13)) * 1274126177;
return h ^ (h >> 16);
}
public static int getSeed(int seed, int x, int y, int z) {
int h = seed + x * 374761393 + y * 668265263 + z;
h = (h ^ (h >> 13)) * 1274126177;
return h ^ (h >> 16);
}
}

View file

@ -156,8 +156,6 @@ public abstract class SDF {
}
public void fillRecursive(StructureWorld world, BlockPos start) {
long t = System.currentTimeMillis();
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
Map<BlockPos, PosInfo> addInfo = Maps.newHashMap();
Set<BlockPos> blocks = Sets.newHashSet();
@ -206,8 +204,5 @@ public abstract class SDF {
BlockState state = postProcess.apply(info);
world.setBlock(info.getPos(), state);
});
t = System.currentTimeMillis() - t;
System.out.println("SDF " + t + " ms");
}
}

View file

@ -35,8 +35,8 @@ public class BetterEndBiomeSource extends BiomeSource {
public BetterEndBiomeSource(Registry<Biome> biomeRegistry, long seed) {
super(Collections.emptyList());
this.mapLand = new BiomeMap(seed, 150, BiomeRegistry.LAND_BIOMES);
this.mapVoid = new BiomeMap(seed, 150, BiomeRegistry.VOID_BIOMES);
this.mapLand = new BiomeMap(seed, 250, BiomeRegistry.LAND_BIOMES);
this.mapVoid = new BiomeMap(seed, 250, BiomeRegistry.VOID_BIOMES);
this.centerBiome = biomeRegistry.getOrThrow(BiomeKeys.THE_END);
this.biomeRegistry = biomeRegistry;
this.seed = seed;

View file

@ -37,10 +37,7 @@ public abstract class SDFStructureFeature extends StructureFeatureBase {
int y = chunkGenerator.getHeight(x, z, Type.WORLD_SURFACE_WG);
if (y > 5) {
BlockPos start = new BlockPos(x, y, z);
long t = System.currentTimeMillis();
VoxelPiece piece = new VoxelPiece((world) -> { ((SDFStructureFeature) this.getFeature()).getSDF(start, this.random).fillRecursive(world, start); }, random.nextInt());
t = System.currentTimeMillis() - t;
System.out.println("Structure " + t + " ms");
this.children.add(piece);
}
this.setBoundingBoxFromChildren();

View file

@ -1,33 +1,40 @@
package ru.betterend.world.structures.features;
import java.util.Random;
import net.minecraft.block.Blocks;
import net.minecraft.structure.StructureManager;
import net.minecraft.structure.StructureStart;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import ru.betterend.noise.VoronoiNoise;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.world.Heightmap.Type;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;
import ru.betterend.util.MHelper;
import ru.betterend.util.sdf.SDF;
import ru.betterend.util.sdf.operator.SDFDisplacement;
import ru.betterend.util.sdf.operator.SDFScale;
import ru.betterend.util.sdf.operator.SDFSmoothUnion;
import ru.betterend.util.sdf.operator.SDFTranslate;
import ru.betterend.util.sdf.primitive.SDFCapedCone;
import ru.betterend.world.structures.piece.MountainPiece;
public class StructureMountain extends SDFStructureFeature {
public class StructureMountain extends StructureFeatureBase {
@Override
protected SDF getSDF(BlockPos center, Random random) {
SDFCapedCone cone1 = new SDFCapedCone().setHeight(20F).setRadius1(40F).setRadius2(0F);
SDFCapedCone cone2 = new SDFCapedCone().setHeight(10F).setRadius1(0F).setRadius2(40F);
cone1.setBlock(Blocks.END_STONE);
cone2.setBlock(Blocks.END_STONE);
SDF mountain = new SDFSmoothUnion().setRadius(15)
.setSourceA(new SDFTranslate().setTranslate(0, 20, 1).setSource(cone1))
.setSourceB(new SDFTranslate().setTranslate(0, -10, 1).setSource(cone2));
mountain = new SDFScale().setScale(MHelper.randRange(1F, 2.5F, random)).setSource(mountain);
VoronoiNoise noise = new VoronoiNoise(random.nextInt(), 20, 0.75);
mountain = new SDFDisplacement().setFunction((pos) -> {
return (float) noise.sample(pos.getX(), pos.getY(), pos.getZ()) * 15F;
}).setSource(mountain);
return mountain;
public StructureFeature.StructureStartFactory<DefaultFeatureConfig> getStructureStartFactory() {
return SDFStructureStart::new;
}
public static class SDFStructureStart extends StructureStart<DefaultFeatureConfig> {
public SDFStructureStart(StructureFeature<DefaultFeatureConfig> feature, int chunkX, int chunkZ, BlockBox box, int references, long seed) {
super(feature, chunkX, chunkZ, box, references, seed);
}
@Override
public void init(DynamicRegistryManager registryManager, ChunkGenerator chunkGenerator, StructureManager manager, int chunkX, int chunkZ, Biome biome, DefaultFeatureConfig config) {
int x = (chunkX << 4) | MHelper.randRange(4, 12, random);
int z = (chunkZ << 4) | MHelper.randRange(4, 12, random);
int y = chunkGenerator.getHeight(x, z, Type.WORLD_SURFACE_WG);
if (y > 5) {
float radius = MHelper.randRange(50, 100, random);
float height = radius * MHelper.randRange(0.8F, 1.2F, random);
this.children.add(new MountainPiece(new BlockPos(x, y, z), radius, height, random.nextInt()));
}
this.setBoundingBoxFromChildren();
}
}
}

View file

@ -0,0 +1,140 @@
package ru.betterend.world.structures.piece;
import java.util.Random;
import net.minecraft.block.Blocks;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.structure.StructureManager;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.Mutable;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.Heightmap.Type;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import ru.betterend.noise.OpenSimplexNoise;
import ru.betterend.registry.BiomeRegistry;
import ru.betterend.registry.StructureRegistry;
import ru.betterend.util.MHelper;
public class MountainPiece extends BasePiece {
private OpenSimplexNoise noise;
private BlockPos center;
private float radius;
private float height;
private float r2;
public MountainPiece(BlockPos center, float radius, float height, int id) {
super(StructureRegistry.MOUNTAIN_PIECE, id);
this.center = center;
this.radius = radius;
this.height = height;
this.r2 = radius * radius;
this.noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ()));
makeBoundingBox();
}
public MountainPiece(StructureManager manager, CompoundTag tag) {
super(StructureRegistry.MOUNTAIN_PIECE, tag);
makeBoundingBox();
}
@Override
protected void toNbt(CompoundTag tag) {
tag.put("center", NbtHelper.fromBlockPos(center));
tag.putFloat("radius", radius);
tag.putFloat("height", height);
}
@Override
protected void fromNbt(CompoundTag tag) {
center = NbtHelper.toBlockPos(tag.getCompound("center"));
radius = tag.getFloat("radius");
height = tag.getFloat("height");
r2 = radius * radius;
noise = new OpenSimplexNoise(MHelper.getSeed(534, center.getX(), center.getZ()));
}
@Override
public boolean generate(StructureWorldAccess world, StructureAccessor arg, ChunkGenerator chunkGenerator, Random random, BlockBox blockBox, ChunkPos chunkPos, BlockPos blockPos) {
int sx = chunkPos.getStartX();
int sz = chunkPos.getStartZ();
Mutable pos = new Mutable();
Chunk chunk = world.getChunk(chunkPos.x, chunkPos.z);
for (int x = 0; x < 16; x++) {
int px = x + sx;
int px2 = px - center.getX();
px2 *= px2;
pos.setX(x);
for (int z = 0; z < 16; z++) {
int pz = z + sz;
int pz2 = pz - center.getZ();
pz2 *= pz2;
float dist = px2 + pz2;
if (dist < r2) {
pos.setZ(z);
dist = 1 - (float) Math.pow(dist / r2, 0.3);
int minY = world.getTopY(Type.WORLD_SURFACE_WG, px, pz);
if (minY > 56) {
float maxY = dist * height * getHeightClamp(world, 8, px, pz);
if (maxY > 0) {
maxY *= (float) noise.eval(px * 0.05, pz * 0.05) * 0.3F + 0.7F;
maxY *= (float) noise.eval(px * 0.1, pz * 0.1) * 0.1F + 0.8F;
maxY += minY;
for (int y = minY; y < maxY; y++) {
pos.setY(y);
chunk.setBlockState(pos, Blocks.END_STONE.getDefaultState(), false);
}
}
}
}
}
}
return true;
}
private int getHeight(StructureWorldAccess world, BlockPos pos) {
if (BiomeRegistry.getFromBiome(world.getBiome(pos)) != BiomeRegistry.END_HIGHLANDS) {
return -4;
}
int h = world.getTopY(Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ());
if (h < 57) {
return 0;
}
return h - 57;
}
private float getHeightClamp(StructureWorldAccess world, int radius, int posX, int posZ) {
Mutable mut = new Mutable();
int r2 = radius * radius;
float height = 0;
float max = 0;
for (int x = -radius; x <= radius; x++) {
mut.setX(posX + x);
int x2 = x * x;
for (int z = -radius; z <= radius; z++) {
mut.setZ(posZ + z);
int z2 = z * z;
if (x2 + z2 < r2) {
float mult = 1 - (float) Math.sqrt(x2 + z2) / radius;
max += mult;
height += getHeight(world, mut) * mult;
}
}
}
height /= max;
return MathHelper.clamp(height / radius, 0, 1);
}
private void makeBoundingBox() {
int minX = MHelper.floor(center.getX() - radius);
int minZ = MHelper.floor(center.getZ() - radius);
int maxX = MHelper.floor(center.getX() + radius + 1);
int maxZ = MHelper.floor(center.getZ() + radius + 1);
this.boundingBox = new BlockBox(minX, minZ, maxX, maxZ);
}
}

View file

@ -34,6 +34,7 @@ public class VoxelPiece extends BasePiece {
tag.put("world", world.toBNT());
}
@Override
protected void fromNbt(CompoundTag tag) {
world = new StructureWorld(tag.getCompound("world"));
}