diff --git a/src/main/java/ru/betterend/registry/FeatureRegistry.java b/src/main/java/ru/betterend/registry/FeatureRegistry.java index 314631f2..198e671b 100644 --- a/src/main/java/ru/betterend/registry/FeatureRegistry.java +++ b/src/main/java/ru/betterend/registry/FeatureRegistry.java @@ -32,6 +32,7 @@ public class FeatureRegistry { // Ores // public static final EndFeature ENDER_ORE = EndFeature.makeOreFeature("ender_ore", BlockRegistry.ENDER_ORE, 6, 3, 0, 4, 96); + public static final EndFeature VIOLECITE_LAYER = EndFeature.makeLayerFeature("violecite_layer", BlockRegistry.VIOLECITE, 15, 4, 96, 8); public static void register() {} } diff --git a/src/main/java/ru/betterend/world/biome/BiomeChorusForest.java b/src/main/java/ru/betterend/world/biome/BiomeChorusForest.java index 964ee007..826439ff 100644 --- a/src/main/java/ru/betterend/world/biome/BiomeChorusForest.java +++ b/src/main/java/ru/betterend/world/biome/BiomeChorusForest.java @@ -19,6 +19,7 @@ public class BiomeChorusForest extends EndBiome { .setLoop(SoundRegistry.AMBIENT_CHORUS_FOREST) .setMusic(SoundRegistry.MUSIC_CHORUS_FOREST) .addFeature(FeatureRegistry.ENDER_ORE) + .addFeature(FeatureRegistry.VIOLECITE_LAYER) .addFeature(FeatureRegistry.RARE_END_LAKE) .addFeature(FeatureRegistry.PYTHADENDRON_TREE) .addFeature(FeatureRegistry.PYTHADENDRON_BUSH) diff --git a/src/main/java/ru/betterend/world/features/EndFeature.java b/src/main/java/ru/betterend/world/features/EndFeature.java index 77ac47db..972b8a28 100644 --- a/src/main/java/ru/betterend/world/features/EndFeature.java +++ b/src/main/java/ru/betterend/world/features/EndFeature.java @@ -1,6 +1,7 @@ package ru.betterend.world.features; import net.minecraft.block.Block; +import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.structure.rule.BlockMatchRuleTest; import net.minecraft.util.Identifier; @@ -18,6 +19,7 @@ import net.minecraft.world.gen.feature.Feature; import net.minecraft.world.gen.feature.FeatureConfig; import net.minecraft.world.gen.feature.OreFeatureConfig; import ru.betterend.BetterEnd; +import ru.betterend.blocks.complex.StoneMaterial; public class EndFeature { private Feature feature; @@ -73,6 +75,24 @@ public class EndFeature { return newFeature; } + public static EndFeature makeLayerFeature(String name, BlockState state, float radius, int minY, int maxY, int count) { + OreLayerFeature layer = new OreLayerFeature(state, radius, minY, maxY); + ConfiguredFeature configured = layer.configure(FeatureConfig.DEFAULT).decorate(Decorator.COUNT.configure(new CountConfig(count))); + return new EndFeature(name, layer, GenerationStep.Feature.UNDERGROUND_ORES, configured); + } + + public static EndFeature makeLayerFeature(String name, Block block, float radius, int minY, int maxY, int count) { + OreLayerFeature layer = new OreLayerFeature(block.getDefaultState(), radius, minY, maxY); + ConfiguredFeature configured = layer.configure(FeatureConfig.DEFAULT).decorate(Decorator.COUNT.configure(new CountConfig(count))); + return new EndFeature(name, layer, GenerationStep.Feature.UNDERGROUND_ORES, configured); + } + + public static EndFeature makeLayerFeature(String name, StoneMaterial material, float radius, int minY, int maxY, int count) { + OreLayerFeature layer = new OreLayerFeature(material.stone.getDefaultState(), radius, minY, maxY); + ConfiguredFeature configured = layer.configure(FeatureConfig.DEFAULT).decorate(Decorator.COUNT.configure(new CountConfig(count))); + return new EndFeature(name, layer, GenerationStep.Feature.UNDERGROUND_ORES, configured); + } + public static EndFeature makeChunkFeature(String name, Feature feature) { ConfiguredFeature configured = feature.configure(FeatureConfig.DEFAULT).decorate(Decorator.COUNT.configure(new CountConfig(1))); return new EndFeature(name, feature, GenerationStep.Feature.LOCAL_MODIFICATIONS, configured); diff --git a/src/main/java/ru/betterend/world/features/OldPythadendronTreeFeature.java b/src/main/java/ru/betterend/world/features/OldPythadendronTreeFeature.java deleted file mode 100644 index cd466546..00000000 --- a/src/main/java/ru/betterend/world/features/OldPythadendronTreeFeature.java +++ /dev/null @@ -1,114 +0,0 @@ -package ru.betterend.world.features; - -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.block.Material; -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.noise.OpenSimplexNoise; -import ru.betterend.registry.BlockRegistry; -import ru.betterend.registry.BlockTagRegistry; -import ru.betterend.util.MHelper; -import ru.betterend.util.SplineHelper; -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.SDFTranslate; -import ru.betterend.util.sdf.operator.SDFUnion; -import ru.betterend.util.sdf.primitive.SDFSphere; - -@Deprecated -public class OldPythadendronTreeFeature extends DefaultFeature { - private static final Function REPLACE; - - @Override - public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { - if (world.getBlockState(pos.down()).getBlock() != BlockRegistry.CHORUS_NYLIUM) return false; - - float size = MHelper.randRange(10, 13, random); - List> splines = Lists.newArrayList(); - List spline = SplineHelper.makeSpline(0, 0, 0, 0, size, 0, 4); - SplineHelper.offsetParts(spline, random, 0.7F, 0, 0.7F); - Vector3f last = spline.get(spline.size() - 1); - List ends = Lists.newArrayList(); - branch(splines, ends, last.getX(), last.getY(), last.getZ(), size * 0.6F, MHelper.randRange(0, MHelper.PI2, random), random, MHelper.floor(Math.log(size) * 1.5F)); - - SDF function = SplineHelper.buildSDF(spline, 1.4F, 0.8F, (bpos) -> { - return BlockRegistry.PYTHADENDRON.bark.getDefaultState(); - }); - - for (List sp: splines) { - float width = 0.8F - (sp.get(0).getY() - size) / 40; - SDF funcSp = SplineHelper.buildSDF(sp, width, width, (bpos) -> { - return BlockRegistry.PYTHADENDRON.bark.getDefaultState(); - }); - function = new SDFUnion().setSourceA(function).setSourceB(funcSp); - } - - OpenSimplexNoise noise = new OpenSimplexNoise(random.nextInt()); - for (Vector3f v: ends) { - SDF sphere = new SDFSphere().setRadius(MHelper.randRange(2.5F, 3.5F, random)).setBlock(BlockRegistry.PYTHADENDRON_LEAVES); - sphere = new SDFTranslate().setTranslate(v.getX(), v.getY(), v.getZ()).setSource(sphere); - sphere = new SDFDisplacement().setFunction((vec) -> { return (float) noise.eval(vec.getX() * 0.2, vec.getY() * 0.2, vec.getZ() * 0.2); }).setSource(sphere); - function = new SDFUnion().setSourceA(function).setSourceB(sphere); - } - - function = new SDFScale().setScale(MHelper.randRange(1.6F, 2.0F, random)).setSource(function); - function.setReplaceFunction(REPLACE); - function.fillRecursive(world, pos); - - return true; - } - - private void branch(List> splines, List ends, float x, float y, float z, float size, float angle, Random random, int depth) { - if (depth == 0) return; - - float dx = (float) Math.cos(angle) * size * 0.3F; - float dz = (float) Math.sin(angle) * size * 0.3F; - - float x1 = x + dx; - float z1 = z + dz; - float x2 = x - dx; - float z2 = z - dz; - - List spline = SplineHelper.makeSpline(x, y, z, x1, y, z1, 5); - SplineHelper.powerOffset(spline, size, 2); - SplineHelper.offsetParts(spline, random, 0.3F, 0, 0.3F); - splines.add(spline); - Vector3f pos1 = spline.get(spline.size() - 1); - - spline = SplineHelper.makeSpline(x, y, z, x2, y, z2, 5); - SplineHelper.powerOffset(spline, size, 2); - SplineHelper.offsetParts(spline, random, 0.3F, 0, 0.3F); - splines.add(spline); - Vector3f pos2 = spline.get(spline.size() - 1); - - if (depth == 1) { - ends.add(pos1); - ends.add(pos2); - } - - branch(splines, ends, pos1.getX(), pos1.getY(), pos1.getZ(), size * 0.8F, angle + (float) Math.PI * 0.5F, random, depth - 1); - branch(splines, ends, pos2.getX(), pos2.getY(), pos2.getZ(), size * 0.8F, angle + (float) Math.PI * 0.5F, random, depth - 1); - } - - static { - REPLACE = (state) -> { - if (state.isIn(BlockTagRegistry.END_GROUND)) { - return true; - } - if (state.getMaterial().equals(Material.PLANT)) { - return true; - } - return state.getMaterial().isReplaceable(); - }; - } -} diff --git a/src/main/java/ru/betterend/world/features/OreLayerFeature.java b/src/main/java/ru/betterend/world/features/OreLayerFeature.java new file mode 100644 index 00000000..ae85e5de --- /dev/null +++ b/src/main/java/ru/betterend/world/features/OreLayerFeature.java @@ -0,0 +1,72 @@ +package ru.betterend.world.features; + +import java.util.Random; + +import net.minecraft.block.BlockState; +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.util.MHelper; +import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFCoordModify; +import ru.betterend.util.sdf.operator.SDFScale3D; +import ru.betterend.util.sdf.primitive.SDFSphere; + +public class OreLayerFeature extends DefaultFeature { + private static final SDFSphere SPHERE; + private static final SDFCoordModify NOISE; + private static final SDF FUNCTION; + + private final BlockState state; + private final float radius; + private final int minY; + private final int maxY; + private OpenSimplexNoise noise; + + public OreLayerFeature(BlockState state, float radius, int minY, int maxY) { + this.state = state; + this.radius = radius; + this.minY = minY; + this.maxY = maxY; + } + + @Override + public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + float radius = this.radius * 0.5F; + int r = MHelper.floor(radius + 1); + int posX = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getX(); + int posZ = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getZ(); + int posY = MHelper.randRange(minY, maxY, random); + + if (noise == null) { + noise = new OpenSimplexNoise(world.getSeed()); + } + + SPHERE.setRadius(radius).setBlock(state); + NOISE.setFunction((vec) -> { + double x = (vec.getX() + pos.getX()) * 0.1; + double z = (vec.getZ() + pos.getZ()) * 0.1; + double offset = noise.eval(x, z); + vec.set(vec.getX(), vec.getY() + (float) offset * 8, vec.getZ()); + }); + FUNCTION.fillRecursive(world, new BlockPos(posX, posY, posZ)); + return true; + } + + static { + SPHERE = new SDFSphere(); + NOISE = new SDFCoordModify(); + + SDF body = SPHERE; + body = new SDFScale3D().setScale(1, 0.2F, 1).setSource(body); + body = NOISE.setSource(body); + body.setReplaceFunction((state) -> { + return state.isOf(Blocks.END_STONE); + }); + + FUNCTION = body; + } +}