Giant Mushroom
This commit is contained in:
parent
2afdc1e2eb
commit
150b005257
12 changed files with 288 additions and 6 deletions
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<PosInfo, BlockState> postProcess = (info) -> {
|
||||
|
@ -120,4 +121,44 @@ public abstract class SDF {
|
|||
|
||||
return mapWorld.keySet();
|
||||
}
|
||||
|
||||
public Set<BlockPos> fillRecursive(StructureWorld world, BlockPos start) {
|
||||
Map<BlockPos, PosInfo> mapWorld = Maps.newHashMap();
|
||||
Set<BlockPos> blocks = Sets.newHashSet();
|
||||
Set<BlockPos> ends = Sets.newHashSet();
|
||||
Set<BlockPos> 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();
|
||||
}
|
||||
}
|
||||
|
|
15
src/main/java/ru/betterend/util/sdf/operator/SDFRound.java
Normal file
15
src/main/java/ru/betterend/util/sdf/operator/SDFRound.java
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<DefaultFeatureConfig> structure;
|
||||
private final ConfiguredStructureFeature<?, ?> featureConfigured;
|
||||
private final GenerationStep.Feature featureStep;
|
||||
|
||||
public EndStructureFeature(String name, StructureFeature<DefaultFeatureConfig> 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<DefaultFeatureConfig> getStructure() {
|
||||
return structure;
|
||||
}
|
||||
|
||||
public ConfiguredStructureFeature<?, ?> getFeatureConfigured() {
|
||||
return featureConfigured;
|
||||
}
|
||||
|
||||
public GenerationStep.Feature getFeatureStep() {
|
||||
return featureStep;
|
||||
}
|
||||
}
|
|
@ -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<DefaultFeatureConfig> {
|
||||
public SDFStructureFeature() {
|
||||
super(DefaultFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
protected abstract SDF getSDF(BlockPos pos, Random random);
|
||||
|
||||
@Override
|
||||
public StructureFeature.StructureStartFactory<DefaultFeatureConfig> getStructureStartFactory() {
|
||||
return SDFStructureStart::new;
|
||||
}
|
||||
|
||||
public static class SDFStructureStart extends StructureStart<DefaultFeatureConfig> {
|
||||
public SDFStructureStart(StructureFeature<DefaultFeatureConfig> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Vector3f> 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();
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue