From 150b005257b3bb1142c68ec7e488cfa422f33196 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Tue, 6 Oct 2020 12:26:13 +0300 Subject: [PATCH] Giant Mushroom --- src/main/java/ru/betterend/BetterEnd.java | 2 + .../betterend/registry/StructureRegistry.java | 9 +- src/main/java/ru/betterend/util/sdf/SDF.java | 41 ++++++ .../betterend/util/sdf/operator/SDFRound.java | 15 +++ .../world/biome/BiomeDefinition.java | 6 + .../world/biome/BiomeFoggyMushroomland.java | 2 + .../features/MossyGlowshroomFeature.java | 4 - .../betterend/world/features/VineFeature.java | 2 +- .../world/structures/EndStructureFeature.java | 46 +++++++ .../features/SDFStructureFeature.java | 47 +++++++ .../StructureGiantMossyGlowshroom.java | 119 ++++++++++++++++++ .../world/structures/piece/VoxelPiece.java | 1 + 12 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 src/main/java/ru/betterend/util/sdf/operator/SDFRound.java create mode 100644 src/main/java/ru/betterend/world/structures/EndStructureFeature.java create mode 100644 src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java create mode 100644 src/main/java/ru/betterend/world/structures/features/StructureGiantMossyGlowshroom.java diff --git a/src/main/java/ru/betterend/BetterEnd.java b/src/main/java/ru/betterend/BetterEnd.java index a381077d..32a04c43 100644 --- a/src/main/java/ru/betterend/BetterEnd.java +++ b/src/main/java/ru/betterend/BetterEnd.java @@ -14,6 +14,7 @@ import ru.betterend.registry.FeatureRegistry; import ru.betterend.registry.ItemRegistry; import ru.betterend.registry.ItemTagRegistry; import ru.betterend.registry.SoundRegistry; +import ru.betterend.registry.StructureRegistry; import ru.betterend.util.Logger; import ru.betterend.world.generator.BetterEndBiomeSource; import ru.betterend.world.surface.DoubleBlockSurfaceBuilder; @@ -38,6 +39,7 @@ public class BetterEnd implements ModInitializer { BlockTagRegistry.register(); CraftingRecipes.register(); AlloyingRecipes.register(); + StructureRegistry.register(); } public static Identifier makeID(String path) { diff --git a/src/main/java/ru/betterend/registry/StructureRegistry.java b/src/main/java/ru/betterend/registry/StructureRegistry.java index c555fb85..a4f1e987 100644 --- a/src/main/java/ru/betterend/registry/StructureRegistry.java +++ b/src/main/java/ru/betterend/registry/StructureRegistry.java @@ -2,11 +2,18 @@ package ru.betterend.registry; import net.minecraft.structure.StructurePieceType; import net.minecraft.util.registry.Registry; +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.VoxelPiece; public class StructureRegistry { - public static final StructurePieceType VOXEL_PIECE = register("sdf", VoxelPiece::new); + public static final StructurePieceType VOXEL_PIECE = register("voxel", VoxelPiece::new); + + public static final EndStructureFeature GIANT_MOSSY_GLOWSHROOM = new EndStructureFeature("giant_mossy_glowshroom", new StructureGiantMossyGlowshroom(), Feature.RAW_GENERATION, 32, 8); + + public static void register() {} private static StructurePieceType register(String id, StructurePieceType pieceType) { return Registry.register(Registry.STRUCTURE_PIECE, BetterEnd.makeID(id), pieceType); diff --git a/src/main/java/ru/betterend/util/sdf/SDF.java b/src/main/java/ru/betterend/util/sdf/SDF.java index d3dc2bb8..b9a532b4 100644 --- a/src/main/java/ru/betterend/util/sdf/SDF.java +++ b/src/main/java/ru/betterend/util/sdf/SDF.java @@ -12,6 +12,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.ServerWorldAccess; import ru.betterend.util.BlocksHelper; +import ru.betterend.world.structures.StructureWorld; public abstract class SDF { private Function postProcess = (info) -> { @@ -120,4 +121,44 @@ public abstract class SDF { return mapWorld.keySet(); } + + public Set fillRecursive(StructureWorld world, BlockPos start) { + Map mapWorld = Maps.newHashMap(); + Set blocks = Sets.newHashSet(); + Set ends = Sets.newHashSet(); + Set add = Sets.newHashSet(); + ends.add(new BlockPos(0, 0, 0)); + boolean run = true; + + while (run) { + for (BlockPos center: ends) { + for (Direction dir: Direction.values()) { + BlockPos pos = center.offset(dir); + BlockPos wpos = pos.add(start); + + if (!blocks.contains(pos)) { + if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) { + BlockState state = getBlockState(wpos); + PosInfo.create(mapWorld, wpos).setState(state); + add.add(pos); + } + } + } + } + + blocks.addAll(ends); + ends.clear(); + ends.addAll(add); + add.clear(); + + run &= !ends.isEmpty(); + } + + mapWorld.forEach((pos, info) -> { + BlockState state = postProcess.apply(info); + world.setBlock(pos, state); + }); + + return mapWorld.keySet(); + } } diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFRound.java b/src/main/java/ru/betterend/util/sdf/operator/SDFRound.java new file mode 100644 index 00000000..fe081381 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFRound.java @@ -0,0 +1,15 @@ +package ru.betterend.util.sdf.operator; + +public class SDFRound extends SDFUnary { + private float radius; + + public SDFRound setRadius(float radius) { + this.radius = radius; + return this; + } + + @Override + public float getDistance(float x, float y, float z) { + return this.source.getDistance(x, y, z) - radius; + } +} diff --git a/src/main/java/ru/betterend/world/biome/BiomeDefinition.java b/src/main/java/ru/betterend/world/biome/BiomeDefinition.java index fc94591d..aa43737f 100644 --- a/src/main/java/ru/betterend/world/biome/BiomeDefinition.java +++ b/src/main/java/ru/betterend/world/biome/BiomeDefinition.java @@ -33,6 +33,7 @@ import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig; import ru.betterend.BetterEnd; import ru.betterend.util.MHelper; import ru.betterend.world.features.EndFeature; +import ru.betterend.world.structures.EndStructureFeature; import ru.betterend.world.surface.DoubleBlockSurfaceBuilder; public class BiomeDefinition { @@ -112,6 +113,11 @@ public class BiomeDefinition { return this; } + public BiomeDefinition addStructureFeature(EndStructureFeature feature) { + structures.add(feature.getFeatureConfigured()); + return this; + } + public BiomeDefinition addFeature(EndFeature feature) { FeatureInfo info = new FeatureInfo(); info.featureStep = feature.getFeatureStep(); diff --git a/src/main/java/ru/betterend/world/biome/BiomeFoggyMushroomland.java b/src/main/java/ru/betterend/world/biome/BiomeFoggyMushroomland.java index d494512b..bb1e2fce 100644 --- a/src/main/java/ru/betterend/world/biome/BiomeFoggyMushroomland.java +++ b/src/main/java/ru/betterend/world/biome/BiomeFoggyMushroomland.java @@ -6,6 +6,7 @@ import ru.betterend.registry.EntityRegistry; import ru.betterend.registry.FeatureRegistry; import ru.betterend.registry.ParticleRegistry; import ru.betterend.registry.SoundRegistry; +import ru.betterend.registry.StructureRegistry; public class BiomeFoggyMushroomland extends EndBiome { public BiomeFoggyMushroomland() { @@ -18,6 +19,7 @@ public class BiomeFoggyMushroomland extends EndBiome { .setParticles(ParticleRegistry.GLOWING_SPHERE, 0.001F) .setLoop(SoundRegistry.AMBIENT_FOGGY_MUSHROOMLAND) .setMusic(SoundRegistry.MUSIC_FOGGY_MUSHROOMLAND) + .addStructureFeature(StructureRegistry.GIANT_MOSSY_GLOWSHROOM) .addFeature(FeatureRegistry.ENDER_ORE) .addFeature(FeatureRegistry.END_LAKE) .addFeature(FeatureRegistry.MOSSY_GLOWSHROOM) diff --git a/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java b/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java index 3f64ce72..85364689 100644 --- a/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java +++ b/src/main/java/ru/betterend/world/features/MossyGlowshroomFeature.java @@ -78,10 +78,6 @@ public class MossyGlowshroomFeature extends DefaultFeature { Vector3f pos = spline.get(spline.size() - 1); float scale = MHelper.randRange(0.75F, 1.1F, random); - if (featureConfig != null && random.nextInt(32) == 0) { - scale *= MHelper.randRange(2F, 3F, random); - } - Vector3f vec = spline.get(0); float x1 = blockPos.getX() + vec.getX() * scale; float y1 = blockPos.getY() + vec.getY() * scale; diff --git a/src/main/java/ru/betterend/world/features/VineFeature.java b/src/main/java/ru/betterend/world/features/VineFeature.java index c4cddc5e..5ffb6e92 100644 --- a/src/main/java/ru/betterend/world/features/VineFeature.java +++ b/src/main/java/ru/betterend/world/features/VineFeature.java @@ -21,7 +21,7 @@ public class VineFeature extends InvertedScatterFeature { @Override public boolean canGenerate(StructureWorldAccess world, Random random, BlockPos center, BlockPos blockPos, float radius) { - return vineBlock.canPlaceAt(AIR, world, blockPos); + return world.isAir(blockPos) && vineBlock.canPlaceAt(AIR, world, blockPos); } @Override diff --git a/src/main/java/ru/betterend/world/structures/EndStructureFeature.java b/src/main/java/ru/betterend/world/structures/EndStructureFeature.java new file mode 100644 index 00000000..f883fbaa --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/EndStructureFeature.java @@ -0,0 +1,46 @@ +package ru.betterend.world.structures; + +import java.util.Random; + +import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.gen.feature.ConfiguredStructureFeature; +import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import net.minecraft.world.gen.feature.StructureFeature; +import ru.betterend.BetterEnd; + +public class EndStructureFeature { + private static final Random RANDOM = new Random(354); + private final StructureFeature structure; + private final ConfiguredStructureFeature featureConfigured; + private final GenerationStep.Feature featureStep; + + public EndStructureFeature(String name, StructureFeature structure, GenerationStep.Feature step, int spacing, int separation) { + Identifier id = BetterEnd.makeID(name); + + this.featureStep = step; + this.structure = FabricStructureBuilder.create(id, structure) + .step(step) + .defaultConfig(spacing, separation, RANDOM.nextInt(8192)) + .adjustsSurface() + .register(); + + this.featureConfigured = this.structure.configure(DefaultFeatureConfig.DEFAULT); + + BuiltinRegistries.add(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, id, this.featureConfigured); + } + + public StructureFeature getStructure() { + return structure; + } + + public ConfiguredStructureFeature getFeatureConfigured() { + return featureConfigured; + } + + public GenerationStep.Feature getFeatureStep() { + return featureStep; + } +} diff --git a/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java b/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java new file mode 100644 index 00000000..baee4af4 --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/features/SDFStructureFeature.java @@ -0,0 +1,47 @@ +package ru.betterend.world.structures.features; + +import java.util.Random; + +import net.minecraft.structure.StructureManager; +import net.minecraft.structure.StructureStart; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +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.world.structures.piece.VoxelPiece; + +public abstract class SDFStructureFeature extends StructureFeature { + public SDFStructureFeature() { + super(DefaultFeatureConfig.CODEC); + } + + protected abstract SDF getSDF(BlockPos pos, Random random); + + @Override + 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); + BlockPos start = new BlockPos(x, y, z); + VoxelPiece piece = new VoxelPiece((world) -> { ((SDFStructureFeature) this.getFeature()).getSDF(start, this.random).fillRecursive(world, start); }, random.nextInt()); + this.children.add(piece); + this.boundingBox = piece.getBoundingBox(); + } + } +} diff --git a/src/main/java/ru/betterend/world/structures/features/StructureGiantMossyGlowshroom.java b/src/main/java/ru/betterend/world/structures/features/StructureGiantMossyGlowshroom.java new file mode 100644 index 00000000..126fb8df --- /dev/null +++ b/src/main/java/ru/betterend/world/structures/features/StructureGiantMossyGlowshroom.java @@ -0,0 +1,119 @@ +package ru.betterend.world.structures.features; + +import java.util.List; +import java.util.Random; +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.util.math.Direction; +import ru.betterend.blocks.BlockMossyGlowshroomCap; +import ru.betterend.noise.OpenSimplexNoise; +import ru.betterend.registry.BlockRegistry; +import ru.betterend.util.MHelper; +import ru.betterend.util.SplineHelper; +import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFBinary; +import ru.betterend.util.sdf.operator.SDFCoordModify; +import ru.betterend.util.sdf.operator.SDFFlatWave; +import ru.betterend.util.sdf.operator.SDFRound; +import ru.betterend.util.sdf.operator.SDFScale; +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.operator.SDFUnion; +import ru.betterend.util.sdf.primitive.SDFCapedCone; +import ru.betterend.util.sdf.primitive.SDFPrimitive; +import ru.betterend.util.sdf.primitive.SDFSphere; + +public class StructureGiantMossyGlowshroom extends SDFStructureFeature { + private static final BlockState AIR = Blocks.AIR.getDefaultState(); + + @Override + protected SDF getSDF(BlockPos center, Random random) { + System.out.println(center); + + SDFCapedCone cone1 = new SDFCapedCone().setHeight(2.5F).setRadius1(1.5F).setRadius2(2.5F); + SDFCapedCone cone2 = new SDFCapedCone().setHeight(3F).setRadius1(2.5F).setRadius2(13F); + SDF posedCone2 = new SDFTranslate().setTranslate(0, 5, 0).setSource(cone2); + SDF posedCone3 = new SDFTranslate().setTranslate(0, 12F, 0).setSource(new SDFScale().setScale(2).setSource(cone2)); + SDF upCone = new SDFSubtraction().setSourceA(posedCone2).setSourceB(posedCone3); + SDF wave = new SDFFlatWave().setRaysCount(12).setIntensity(1.3F).setSource(upCone); + SDF cones = new SDFSmoothUnion().setRadius(3).setSourceA(cone1).setSourceB(wave); + + SDF innerCone = new SDFTranslate().setTranslate(0, 1.25F, 0).setSource(upCone); + innerCone = new SDFScale3D().setScale(1.2F, 1F, 1.2F).setSource(innerCone); + cones = new SDFUnion().setSourceA(cones).setSourceB(innerCone); + + SDF glowCone = new SDFCapedCone().setHeight(3F).setRadius1(2F).setRadius2(12.5F); + SDFPrimitive priGlowCone = (SDFPrimitive) glowCone; + glowCone = new SDFTranslate().setTranslate(0, 4.25F, 0).setSource(glowCone); + glowCone = new SDFSubtraction().setSourceA(glowCone).setSourceB(posedCone3); + + cones = new SDFUnion().setSourceA(cones).setSourceB(glowCone); + + OpenSimplexNoise noise = new OpenSimplexNoise(1234); + cones = new SDFCoordModify().setFunction((pos) -> { + float dist = MHelper.length(pos.getX(), pos.getZ()); + float y = pos.getY() + (float) noise.eval(pos.getX() * 0.1 + center.getX(), pos.getZ() * 0.1 + center.getZ()) * dist * 0.3F - dist * 0.15F; + pos.set(pos.getX(), y, pos.getZ()); + }).setSource(cones); + + SDFTranslate HEAD_POS = (SDFTranslate) new SDFTranslate().setSource(new SDFTranslate().setTranslate(0, 2.5F, 0).setSource(cones)); + + SDF roots = new SDFSphere().setRadius(4F); + SDFPrimitive primRoots = (SDFPrimitive) roots; + roots = new SDFScale3D().setScale(1, 0.7F, 1).setSource(roots); + SDFFlatWave rotRoots = (SDFFlatWave) new SDFFlatWave().setRaysCount(5).setIntensity(1.5F).setSource(roots); + + SDFBinary function = new SDFSmoothUnion().setRadius(4).setSourceB(new SDFUnion().setSourceA(HEAD_POS).setSourceB(rotRoots)); + + cone1.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_CAP); + cone2.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_CAP); + priGlowCone.setBlock(BlockRegistry.MOSSY_GLOWSHROOM_HYMENOPHORE); + primRoots.setBlock(BlockRegistry.MOSSY_GLOWSHROOM.bark); + + 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); + SDF sdf = SplineHelper.buildSDF(spline, 2.1F, 1.5F, (pos) -> { + return BlockRegistry.MOSSY_GLOWSHROOM.log.getDefaultState(); + }); + Vector3f pos = spline.get(spline.size() - 1); + float scale = MHelper.randRange(2F, 3.5F, random); + + HEAD_POS.setTranslate(pos.getX(), pos.getY(), pos.getZ()); + rotRoots.setAngle(random.nextFloat() * MHelper.PI2); + function.setSourceA(sdf); + + return new SDFRound().setRadius(1.5F).setSource(new SDFScale() + .setScale(scale) + .setSource(function) + .setPostProcess((info) -> { + if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getState())) { + if (!BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateUp()) || !BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) { + return BlockRegistry.MOSSY_GLOWSHROOM.bark.getDefaultState(); + } + } + else if (info.getState().getBlock() == BlockRegistry.MOSSY_GLOWSHROOM_CAP) { + if (BlockRegistry.MOSSY_GLOWSHROOM.isTreeLog(info.getStateDown())) { + return info.getState().with(BlockMossyGlowshroomCap.TRANSITION, true); + } + + int air = 0; + for (Direction dir: Direction.values()) { + if (info.getState(dir).isAir()) { + air ++; + } + } + if (air > 4) { + info.setState(AIR); + return AIR; + } + } + return info.getState(); + })); + } +} 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 6a5bda8c..84c56f49 100644 --- a/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java +++ b/src/main/java/ru/betterend/world/structures/piece/VoxelPiece.java @@ -39,6 +39,7 @@ public class VoxelPiece extends BasePiece { @Override public boolean generate(StructureWorldAccess world, StructureAccessor arg, ChunkGenerator chunkGenerator, Random random, BlockBox blockBox, ChunkPos chunkPos, BlockPos blockPos) { + this.world.placeChunk(world, chunkPos); return true; } }