diff --git a/src/main/java/ru/betterend/registry/FeatureRegistry.java b/src/main/java/ru/betterend/registry/FeatureRegistry.java index 5ab4ee9c..fe445ca1 100644 --- a/src/main/java/ru/betterend/registry/FeatureRegistry.java +++ b/src/main/java/ru/betterend/registry/FeatureRegistry.java @@ -8,7 +8,7 @@ import ru.betterend.world.features.StoneSpiralFeature; public class FeatureRegistry { public static final EndFeature STONE_SPIRAL = new EndFeature("stone_spiral", new StoneSpiralFeature(), 2); public static final EndFeature MOSSY_GLOWSHROOM = new EndFeature("mossy_glowshroom", new MossyGlowshroomFeature(), 1); - public static final EndFeature END_LAKE = EndFeature.MakeRawGenFeature("end_lake", new EndLakeFeature(), 100); + public static final EndFeature END_LAKE = EndFeature.MakeLakeFeature("end_lake", new EndLakeFeature(), 100); public static void register() {} } diff --git a/src/main/java/ru/betterend/util/SplineHelper.java b/src/main/java/ru/betterend/util/SplineHelper.java new file mode 100644 index 00000000..8fbedeb0 --- /dev/null +++ b/src/main/java/ru/betterend/util/SplineHelper.java @@ -0,0 +1,61 @@ +package ru.betterend.util; + +import java.util.List; +import java.util.Random; +import java.util.function.Function; + +import com.google.common.collect.Lists; + +import net.minecraft.block.BlockState; +import net.minecraft.client.util.math.Vector3f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import ru.betterend.util.sdf.ISDF; +import ru.betterend.util.sdf.operator.SDFUnion; +import ru.betterend.util.sdf.primitive.SDFLine; + +public class SplineHelper { + public static List makeSpline(float x1, float y1, float z1, float x2, float y2, float z2, int points) { + List spline = Lists.newArrayList(); + spline.add(new Vector3f(x1, y1, z1)); + int count = points - 1; + for (int i = 1; i < count; i++) { + float delta = (float) i / (float) count; + float x = MathHelper.lerp(delta, x1, x2); + float y = MathHelper.lerp(delta, y1, y2); + float z = MathHelper.lerp(delta, z1, z2); + spline.add(new Vector3f(x, y, z)); + } + spline.add(new Vector3f(x2, y2, z2)); + return spline; + } + + public static void offsetParts(List spline, Random random, float dx, float dy, float dz) { + int count = spline.size(); + for (int i = 1; i < count; i++) { + Vector3f pos = spline.get(i); + float x = pos.getX() + (float) random.nextGaussian() * dx; + float y = pos.getY() + (float) random.nextGaussian() * dy; + float z = pos.getZ() + (float) random.nextGaussian() * dz; + pos.set(x, y, z); + } + } + + public static ISDF buildSDF(List spline, float radius1, float radius2, Function placerFunction) { + int count = spline.size(); + float max = count - 2; + ISDF result = null; + Vector3f start = spline.get(0); + for (int i = 1; i < count; i++) { + Vector3f pos = spline.get(i); + float delta = (float) (i - 1) / max; + SDFLine line = new SDFLine(placerFunction) + .setRadius(MathHelper.lerp(delta, radius1, radius2)) + .setStart(start.getX(), start.getY(), start.getZ()) + .setEnd(pos.getX(), pos.getY(), pos.getZ()); + result = result == null ? line : new SDFUnion().setSourceA(result).setSourceB(line); + start = pos; + } + return result; + } +} diff --git a/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java b/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java index 2028d8b1..d7aaa934 100644 --- a/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java +++ b/src/main/java/ru/betterend/util/sdf/primitive/SDFCapedCone.java @@ -37,7 +37,7 @@ public class SDFCapedCone extends SDFPrimitive { @Override public float getDistance(float x, float y, float z) { - float qx = MHelper.length(x, z);; + float qx = MHelper.length(x, z); float k2x = radius2 - radius1; float k2y = 2 * height; float cax = qx - MHelper.min(qx, (y < 0F) ? radius1 : radius2); diff --git a/src/main/java/ru/betterend/world/features/EndFeature.java b/src/main/java/ru/betterend/world/features/EndFeature.java index 6854aa42..cd148a4d 100644 --- a/src/main/java/ru/betterend/world/features/EndFeature.java +++ b/src/main/java/ru/betterend/world/features/EndFeature.java @@ -44,6 +44,11 @@ public class EndFeature { ConfiguredFeature configured = feature.configure(FeatureConfig.DEFAULT).decorate(Decorator.CHANCE.configure(new ChanceDecoratorConfig(100))); return new EndFeature(name, feature, GenerationStep.Feature.RAW_GENERATION, configured); } + + public static EndFeature MakeLakeFeature(String name, Feature feature, int chance) { + ConfiguredFeature configured = feature.configure(FeatureConfig.DEFAULT).decorate(Decorator.CHANCE.configure(new ChanceDecoratorConfig(100))); + return new EndFeature(name, feature, GenerationStep.Feature.LAKES, configured); + } public Feature getFeature() { return feature; diff --git a/src/main/java/ru/betterend/world/features/EndLakeFeature.java b/src/main/java/ru/betterend/world/features/EndLakeFeature.java index a1827005..e729df42 100644 --- a/src/main/java/ru/betterend/world/features/EndLakeFeature.java +++ b/src/main/java/ru/betterend/world/features/EndLakeFeature.java @@ -11,6 +11,7 @@ import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; import ru.betterend.noise.OpenSimplexNoise; import ru.betterend.registry.BlockRegistry; +import ru.betterend.registry.BlockTagRegistry; import ru.betterend.util.BlocksHelper; import ru.betterend.util.MHelper; @@ -61,22 +62,23 @@ public class EndLakeFeature extends DefaultFeature { double r = add * 1.8 + radius * (NOISE.eval(x * 0.2, y * 0.2, z * 0.2) * 0.25 + 0.75); r *= r; if (x2 + z2 <= r) { - if (world.getBlockState(POS).getBlock() == Blocks.END_STONE) + if (world.getBlockState(POS).isIn(BlockTagRegistry.END_GROUND)) { BlocksHelper.setWithoutUpdate(world, POS, AIR); + } pos = POS.down(); - if (world.getBlockState(pos).getBlock() == Blocks.END_STONE) + if (world.getBlockState(pos).isIn(BlockTagRegistry.END_GROUND)) { - BlockState state = world.getBiome(POS).getGenerationSettings().getSurfaceConfig().getTopMaterial(); + BlockState state = world.getBiome(pos).getGenerationSettings().getSurfaceConfig().getTopMaterial(); if (y > waterLevel + 1) - BlocksHelper.setWithoutUpdate(world, POS.down(), state); + BlocksHelper.setWithoutUpdate(world, pos, state); else if (y > waterLevel) - BlocksHelper.setWithoutUpdate(world, POS.down(), random.nextBoolean() ? state : BlockRegistry.ENDSTONE_DUST.getDefaultState()); + BlocksHelper.setWithoutUpdate(world, pos, random.nextBoolean() ? state : BlockRegistry.ENDSTONE_DUST.getDefaultState()); else - BlocksHelper.setWithoutUpdate(world, POS.down(), BlockRegistry.ENDSTONE_DUST.getDefaultState()); + BlocksHelper.setWithoutUpdate(world, pos, BlockRegistry.ENDSTONE_DUST.getDefaultState()); } pos = POS.up(); - if (!world.getBlockState(pos).isAir()) { - while (!world.getBlockState(pos).isAir()) { + if (world.getBlockState(pos).isIn(BlockTagRegistry.END_GROUND)) { + while (world.getBlockState(pos).isIn(BlockTagRegistry.END_GROUND)) { BlocksHelper.setWithoutUpdate(world, pos, AIR); pos = pos.up(); } @@ -106,7 +108,7 @@ public class EndLakeFeature extends DefaultFeature { if (y2 + x2 + z2 <= r) { BlocksHelper.setWithoutUpdate(world, POS, y < waterLevel ? WATER : AIR); pos = POS.down(); - if (world.getBlockState(pos).getBlock() == Blocks.END_STONE) + if (world.getBlockState(pos).getBlock().isIn(BlockTagRegistry.END_GROUND)) BlocksHelper.setWithoutUpdate(world, POS.down(), BlockRegistry.ENDSTONE_DUST.getDefaultState()); pos = POS.up(); if (!world.getBlockState(pos).isAir()) { diff --git a/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java b/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java index 21266268..dd256622 100644 --- a/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java +++ b/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java @@ -1,21 +1,26 @@ package ru.betterend.world.features; +import java.util.List; import java.util.Random; import java.util.function.Function; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.client.util.math.Vector3f; 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.registry.BlockTagRegistry; +import ru.betterend.util.MHelper; +import ru.betterend.util.SplineHelper; import ru.betterend.util.sdf.ISDF; import ru.betterend.util.sdf.operator.SDFFlatWave; import ru.betterend.util.sdf.operator.SDFScale3D; import ru.betterend.util.sdf.operator.SDFSmoothUnion; import ru.betterend.util.sdf.operator.SDFSubtraction; import ru.betterend.util.sdf.operator.SDFTranslate; +import ru.betterend.util.sdf.primitive.SDFCapedCone; import ru.betterend.util.sdf.primitive.SDFLine; import ru.betterend.util.sdf.primitive.SDFSphere; @@ -32,12 +37,22 @@ public class MossyGlowshroomFeature extends DefaultFeature { if (!world.getBlockState(blockPos.down()).isIn(BlockTagRegistry.END_GROUND)) { return false; } - FUNCTION.fillRecursive(world, getTopPos(world, blockPos), REPLACE, 20, 50, 20); + //FUNCTION.fillRecursive(world, getTopPos(world, blockPos), REPLACE, 20, 50, 20); + + float height = MHelper.randRange(10F, 25F, random); + int count = MHelper.floor(height / 4); + List spline = SplineHelper.makeSpline(0, 0, 0, 0, height, 0, count); + SplineHelper.offsetParts(spline, random, 1F, 0, 1F); + ISDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> { + return Blocks.DIAMOND_BLOCK.getDefaultState(); + }); + sdf.fillRecursive(world, blockPos, REPLACE); + return true; } static { - SDFLine stem = new SDFLine(Blocks.GOLD_BLOCK.getDefaultState()).setRadius(2F).setEnd(0, 15, 0); + /*SDFLine stem = new SDFLine(Blocks.GOLD_BLOCK.getDefaultState()).setRadius(2F).setEnd(0, 15, 0); SDFSphere outerSphere = new SDFSphere(Blocks.REDSTONE_BLOCK.getDefaultState()).setRadius(10); SDFSphere innerSphere = new SDFSphere(Blocks.DIAMOND_BLOCK.getDefaultState()).setRadius(10); @@ -51,7 +66,9 @@ public class MossyGlowshroomFeature extends DefaultFeature { SDFTranslate headOffset = new SDFTranslate().setTranslate(0, 15, 0); - FUNCTION = new SDFSmoothUnion().setRadius(5).setSourceA(stem).setSourceB(headOffset.setSource(head)); + FUNCTION = new SDFSmoothUnion().setRadius(5).setSourceA(stem).setSourceB(headOffset.setSource(head));*/ + + FUNCTION = new SDFCapedCone(Blocks.GOLD_BLOCK.getDefaultState()).setHeight(10).setRadius1(0).setRadius2(10); REPLACE = (state) -> { return state.getMaterial().isReplaceable();