diff --git a/src/main/java/ru/betterend/registry/EndFeatures.java b/src/main/java/ru/betterend/registry/EndFeatures.java index ec5a3b41..54555744 100644 --- a/src/main/java/ru/betterend/registry/EndFeatures.java +++ b/src/main/java/ru/betterend/registry/EndFeatures.java @@ -17,6 +17,7 @@ import ru.betterend.world.features.EndFeature; import ru.betterend.world.features.EndLilyFeature; import ru.betterend.world.features.EndLotusFeature; import ru.betterend.world.features.EndLotusLeafFeature; +import ru.betterend.world.features.FloatingSpireFeature; import ru.betterend.world.features.SinglePlantFeature; import ru.betterend.world.features.UnderwaterPlantFeature; import ru.betterend.world.features.VineFeature; @@ -80,6 +81,7 @@ public class EndFeatures { public static final EndFeature ROUND_CAVE = EndFeature.makeRawGenFeature("round_cave", new RoundCaveFeature(), 2); public static final EndFeature ROUND_CAVE_RARE = EndFeature.makeRawGenFeature("round_cave_rare", new RoundCaveFeature(), 25); public static final EndFeature SPIRE = EndFeature.makeRawGenFeature("spire", new SpireFeature(), 2); + public static final EndFeature FLOATING_SPIRE = EndFeature.makeRawGenFeature("floating_spire", new FloatingSpireFeature(), 8); // Ores // public static final EndFeature ENDER_ORE = EndFeature.makeOreFeature("ender_ore", EndBlocks.ENDER_ORE, 6, 3, 0, 4, 96); diff --git a/src/main/java/ru/betterend/world/biome/BlossomingSpires.java b/src/main/java/ru/betterend/world/biome/BlossomingSpires.java index 1c2cd763..2ac6e94e 100644 --- a/src/main/java/ru/betterend/world/biome/BlossomingSpires.java +++ b/src/main/java/ru/betterend/world/biome/BlossomingSpires.java @@ -12,6 +12,7 @@ public class BlossomingSpires extends EndBiome { .setPlantsColor(122, 45, 122) .setSurface(EndBlocks.END_MOSS) .addFeature(EndFeatures.SPIRE) + .addFeature(EndFeatures.FLOATING_SPIRE) .addMobSpawn(EntityType.ENDERMAN, 50, 1, 4)); } } diff --git a/src/main/java/ru/betterend/world/features/FloatingSpireFeature.java b/src/main/java/ru/betterend/world/features/FloatingSpireFeature.java new file mode 100644 index 00000000..c939791a --- /dev/null +++ b/src/main/java/ru/betterend/world/features/FloatingSpireFeature.java @@ -0,0 +1,48 @@ +package ru.betterend.world.features; + +import java.util.Random; + +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.StructureWorldAccess; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import ru.betterend.noise.OpenSimplexNoise; +import ru.betterend.registry.EndBlocks; +import ru.betterend.util.MHelper; +import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFDisplacement; +import ru.betterend.util.sdf.primitive.SDFSphere; +import ru.betterend.world.features.terrain.SpireFeature; + +public class FloatingSpireFeature extends SpireFeature { + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + int minY = getYOnSurface(world, pos.getX(), pos.getZ()); + int y = minY > 57 ? MHelper.floor(MHelper.randRange(minY, minY * 2, random) * 0.5F + 32) : MHelper.randRange(64, 192, random); + pos = new BlockPos(pos.getX(), y, pos.getZ()); + + SDF sdf = new SDFSphere().setRadius(MHelper.randRange(2, 3, random)).setBlock(Blocks.END_STONE); + int count = MHelper.randRange(3, 5, random); + + for (int i = 0; i < count; i++) { + float rMin = (i * 1.3F) + 2.5F; + sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); + } + for (int i = count - 1; i > 0; i--) { + float rMin = (i * 1.3F) + 2.5F; + sdf = addSegment(sdf, MHelper.randRange(rMin, rMin + 1.5F, random), random); + } + + OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong()); + sdf = new SDFDisplacement().setFunction((vec) -> { + return (float) (Math.abs(noise.eval(vec.getX() * 0.1, vec.getY() * 0.1, vec.getZ() * 0.1)) * 3F + Math.abs(noise.eval(vec.getX() * 0.3, vec.getY() * 0.3 + 100, vec.getZ() * 0.3)) * 1.3F); + }).setSource(sdf); + final BlockPos center = pos; + sdf.setReplaceFunction(REPLACE).setPostProcess((info) -> { + return info.getStateUp().isAir() ? EndBlocks.END_MOSS.getDefaultState() : info.getState(); + }); + sdf.fillRecursive(world, center); + return true; + } +} diff --git a/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java b/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java index 42ac3ae5..69309f5b 100644 --- a/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java +++ b/src/main/java/ru/betterend/world/features/terrain/SpireFeature.java @@ -23,7 +23,7 @@ import ru.betterend.util.sdf.primitive.SDFSphere; import ru.betterend.world.features.DefaultFeature; public class SpireFeature extends DefaultFeature { - private static final Function REPLACE; + protected static final Function REPLACE; @Override public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { @@ -49,7 +49,7 @@ public class SpireFeature extends DefaultFeature { return false; } - private SDF addSegment(SDF sdf, float radius, Random random) { + protected SDF addSegment(SDF sdf, float radius, Random random) { SDF sphere = new SDFSphere().setRadius(radius).setBlock(Blocks.END_STONE); SDF offseted = new SDFTranslate().setTranslate(0, radius + random.nextFloat() * 0.25F * radius, 0).setSource(sdf); return new SDFSmoothUnion().setRadius(radius * 0.5F).setSourceA(sphere).setSourceB(offseted);