From 466dd6604d8ead23516bfcb94dc0c7a92594a718 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Wed, 7 Oct 2020 04:48:49 +0300 Subject: [PATCH] Mountains --- .../common/DefaultBiomeCreatorMixin.java | 10 +- .../registry/DefaultBiomeFeatureRegistry.java | 3 +- .../betterend/registry/StructureRegistry.java | 2 + src/main/java/ru/betterend/util/MHelper.java | 12 ++ src/main/java/ru/betterend/util/sdf/SDF.java | 5 - .../world/generator/BetterEndBiomeSource.java | 4 +- .../features/SDFStructureFeature.java | 3 - .../features/StructureMountain.java | 57 +++---- .../world/structures/piece/MountainPiece.java | 140 ++++++++++++++++++ .../world/structures/piece/VoxelPiece.java | 1 + 10 files changed, 198 insertions(+), 39 deletions(-) create mode 100644 src/main/java/ru/betterend/world/structures/piece/MountainPiece.java diff --git a/src/main/java/ru/betterend/mixin/common/DefaultBiomeCreatorMixin.java b/src/main/java/ru/betterend/mixin/common/DefaultBiomeCreatorMixin.java index 6297be87..b9045b22 100644 --- a/src/main/java/ru/betterend/mixin/common/DefaultBiomeCreatorMixin.java +++ b/src/main/java/ru/betterend/mixin/common/DefaultBiomeCreatorMixin.java @@ -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); - }*/ + } } diff --git a/src/main/java/ru/betterend/registry/DefaultBiomeFeatureRegistry.java b/src/main/java/ru/betterend/registry/DefaultBiomeFeatureRegistry.java index fe8eaed0..3765a325 100644 --- a/src/main/java/ru/betterend/registry/DefaultBiomeFeatureRegistry.java +++ b/src/main/java/ru/betterend/registry/DefaultBiomeFeatureRegistry.java @@ -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); } diff --git a/src/main/java/ru/betterend/registry/StructureRegistry.java b/src/main/java/ru/betterend/registry/StructureRegistry.java index 68889457..7d228503 100644 --- a/src/main/java/ru/betterend/registry/StructureRegistry.java +++ b/src/main/java/ru/betterend/registry/StructureRegistry.java @@ -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); diff --git a/src/main/java/ru/betterend/util/MHelper.java b/src/main/java/ru/betterend/util/MHelper.java index 1d9011d6..908a3b60 100644 --- a/src/main/java/ru/betterend/util/MHelper.java +++ b/src/main/java/ru/betterend/util/MHelper.java @@ -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); + } } diff --git a/src/main/java/ru/betterend/util/sdf/SDF.java b/src/main/java/ru/betterend/util/sdf/SDF.java index 6715f794..7bec5f0b 100644 --- a/src/main/java/ru/betterend/util/sdf/SDF.java +++ b/src/main/java/ru/betterend/util/sdf/SDF.java @@ -156,8 +156,6 @@ public abstract class SDF { } public void fillRecursive(StructureWorld world, BlockPos start) { - long t = System.currentTimeMillis(); - Map mapWorld = Maps.newHashMap(); Map addInfo = Maps.newHashMap(); Set 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"); } } diff --git a/src/main/java/ru/betterend/world/generator/BetterEndBiomeSource.java b/src/main/java/ru/betterend/world/generator/BetterEndBiomeSource.java index 14e7539e..4d59444b 100644 --- a/src/main/java/ru/betterend/world/generator/BetterEndBiomeSource.java +++ b/src/main/java/ru/betterend/world/generator/BetterEndBiomeSource.java @@ -35,8 +35,8 @@ public class BetterEndBiomeSource extends BiomeSource { public BetterEndBiomeSource(Registry 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; diff --git a/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java b/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java index 50d0bb33..42a31a73 100644 --- a/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java +++ b/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java @@ -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(); diff --git a/src/main/java/ru/betterend/world/structures/features/StructureMountain.java b/src/main/java/ru/betterend/world/structures/features/StructureMountain.java index 19c7e468..cc6bd7f0 100644 --- a/src/main/java/ru/betterend/world/structures/features/StructureMountain.java +++ b/src/main/java/ru/betterend/world/structures/features/StructureMountain.java @@ -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 getStructureStartFactory() { + return SDFStructureStart::new; + } + + public static class SDFStructureStart extends StructureStart { + public SDFStructureStart(StructureFeature 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(); + } } } diff --git a/src/main/java/ru/betterend/world/structures/piece/MountainPiece.java b/src/main/java/ru/betterend/world/structures/piece/MountainPiece.java new file mode 100644 index 00000000..96a11de2 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/piece/MountainPiece.java @@ -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); + } +} diff --git a/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java b/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java index 85815a70..bc64989a 100644 --- a/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java +++ b/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java @@ -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")); }