Stalactites

This commit is contained in:
paulevsGitch 2021-03-09 07:27:38 +03:00
parent 2ac1ec8f5a
commit 7e73d9a31c
39 changed files with 657 additions and 31 deletions

View file

@ -25,6 +25,7 @@ public class BlockProperties {
public static final IntProperty FULLNESS = IntProperty.of("fullness", 0, 3);
public static final IntProperty COLOR = IntProperty.of("color", 0, 7);
public static final IntProperty PORTAL = IntProperty.of("portal", 0, EndPortals.getCount());
public static final IntProperty SIZE = IntProperty.of("size", 0, 7);
public static enum TripleShape implements StringIdentifiable {
TOP("top"),

View file

@ -0,0 +1,133 @@
package ru.betterend.blocks.basis;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ShapeContext;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.IntProperty;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.Mutable;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import ru.betterend.blocks.BlockProperties;
import ru.betterend.patterns.Patterns;
public class StalactiteBlock extends BlockBaseNotFull {
public static final IntProperty SIZE = BlockProperties.SIZE;
private static final Mutable POS = new Mutable();
private static final VoxelShape[] SHAPES;
private final Block source;
public StalactiteBlock(Block source) {
super(FabricBlockSettings.copy(source).nonOpaque());
this.setDefaultState(getStateManager().getDefaultState().with(SIZE, 0));
this.source = source;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> stateManager) {
stateManager.add(SIZE);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ePos) {
return SHAPES[state.get(SIZE)];
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
if (world.getBlockState(pos.down()).getBlock() instanceof StalactiteBlock) {
POS.setX(pos.getX());
POS.setZ(pos.getZ());
for (int i = 1; i < 8; i++) {
POS.setY(pos.getY() - i);
if (world.getBlockState(POS).getBlock() instanceof StalactiteBlock) {
BlockState state2 = world.getBlockState(POS);
int size = state2.get(SIZE);
if (size < i) {
world.setBlockState(POS, state2.with(SIZE, i));
}
else {
break;
}
}
else {
break;
}
}
}
if (world.getBlockState(pos.up()).getBlock() instanceof StalactiteBlock) {
POS.setX(pos.getX());
POS.setZ(pos.getZ());
for (int i = 1; i < 8; i++) {
POS.setY(pos.getY() + i);
if (world.getBlockState(POS).getBlock() instanceof StalactiteBlock) {
BlockState state2 = world.getBlockState(POS);
int size = state2.get(SIZE);
if (size < i) {
world.setBlockState(POS, state2.with(SIZE, i));
}
else {
break;
}
}
else {
break;
}
}
}
}
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction facing, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
if (!canPlaceAt(state, world, pos)) {
return Blocks.AIR.getDefaultState();
}
else {
return state;
}
}
@Override
public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
BlockState upState = world.getBlockState(pos.up());
BlockState downState = world.getBlockState(pos.down());
int size = state.get(SIZE);
boolean validUp = (upState.isOf(this) && upState.get(SIZE) >= size) || upState.isFullCube(world, pos.up());
boolean validDown = (downState.isOf(this) && downState.get(SIZE) >= size) || downState.isFullCube(world, pos.down());
return validUp || validDown;
}
@Override
public String getModelPattern(String block) {
Identifier blockId = Registry.BLOCK.getId(this);
if (block.contains("item")) {
return Patterns.createJson(Patterns.ITEM_GENERATED, "item/" + blockId.getPath());
}
blockId = Registry.BLOCK.getId(source);
int shape = Character.getNumericValue(block.charAt(block.lastIndexOf('_') + 1));
return Patterns.createJson(Patterns.BLOCKS_STALACTITE[shape], blockId.getNamespace() + ":block/" + blockId.getPath());
}
@Override
public Identifier statePatternId() {
return Patterns.STATE_STALACTITE;
}
static {
SHAPES = new VoxelShape[8];
for (int i = 0; i < 8; i++) {
SHAPES[i] = Block.createCuboidShape(7 - i, 0, 7 - i, 9 + i, 16, 9 + i);
}
}
}

View file

@ -0,0 +1,92 @@
package ru.betterend.particle;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.particle.AnimatedParticle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleFactory;
import net.minecraft.client.particle.ParticleTextureSheet;
import net.minecraft.client.particle.SpriteProvider;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.util.math.MathHelper;
import ru.betterend.util.MHelper;
@Environment(EnvType.CLIENT)
public class SmaragdantParticle extends AnimatedParticle {
private double preVX;
private double preVY;
private double preVZ;
private double nextVX;
private double nextVY;
private double nextVZ;
protected SmaragdantParticle(ClientWorld world, double x, double y, double z, double r, double g, double b, SpriteProvider sprites) {
super(world, x, y, z, sprites, 0);
setSprite(sprites.getSprite(random));
this.maxAge = MHelper.randRange(60, 120, random);
this.scale = MHelper.randRange(0.05F, 0.15F, random);
this.setColor(1, 1, 1);
this.setColorAlpha(0);
preVX = random.nextGaussian() * 0.01;
preVY = random.nextGaussian() * 0.01;
preVZ = random.nextGaussian() * 0.01;
nextVX = random.nextGaussian() * 0.01;
nextVY = random.nextGaussian() * 0.01;
nextVZ = random.nextGaussian() * 0.01;
}
@Override
public void tick() {
int ticks = this.age & 31;
if (ticks == 0) {
preVX = nextVX;
preVY = nextVY;
preVZ = nextVZ;
nextVX = random.nextGaussian() * 0.015;
nextVY = random.nextFloat() * 0.02 + 0.01;
nextVZ = random.nextGaussian() * 0.015;
}
double delta = (double) ticks / 31.0;
if (this.age <= 31) {
this.setColorAlpha(this.age / 31F);
}
else if (this.age >= this.maxAge - 31) {
this.setColorAlpha((this.maxAge - this.age) / 31F);
}
if (this.age >= this.maxAge) {
this.markDead();
}
this.velocityX = MathHelper.lerp(delta, preVX, nextVX);
this.velocityY = MathHelper.lerp(delta, preVY, nextVY);
this.velocityZ = MathHelper.lerp(delta, preVZ, nextVZ);
super.tick();
}
@Override
public ParticleTextureSheet getType() {
return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT;
}
@Environment(EnvType.CLIENT)
public static class SmaragdantParticleFactory implements ParticleFactory<DefaultParticleType> {
private final SpriteProvider sprites;
public SmaragdantParticleFactory(SpriteProvider sprites) {
this.sprites = sprites;
}
@Override
public Particle createParticle(DefaultParticleType type, ClientWorld world, double x, double y, double z, double vX, double vY, double vZ) {
return new SmaragdantParticle(world, x, y, z, 1, 1, 1, sprites);
}
}
}

View file

@ -46,6 +46,7 @@ public class Patterns {
public final static Identifier STATE_CHANDELIER = BetterEnd.makeID("patterns/blockstate/chandelier.json");
public final static Identifier STATE_FURNACE = BetterEnd.makeID("patterns/blockstate/furnace.json");
public final static Identifier STATE_ROTATED_TOP = BetterEnd.makeID("patterns/blockstate/rotated_top.json");
public final static Identifier STATE_STALACTITE = BetterEnd.makeID("patterns/blockstate/stalactite.json");
//Models Block
public final static Identifier BLOCK_EMPTY = BetterEnd.makeID("patterns/block/empty.json");
@ -104,6 +105,17 @@ public class Patterns {
public final static Identifier BLOCK_TOP_SIDE_BOTTOM = BetterEnd.makeID("patterns/block/top_side_bottom.json");
public final static Identifier BLOCK_PATH = BetterEnd.makeID("patterns/block/path.json");
public final static Identifier[] BLOCKS_STALACTITE = new Identifier[] {
BetterEnd.makeID("patterns/block/stalactite_0.json"),
BetterEnd.makeID("patterns/block/stalactite_1.json"),
BetterEnd.makeID("patterns/block/stalactite_2.json"),
BetterEnd.makeID("patterns/block/stalactite_3.json"),
BetterEnd.makeID("patterns/block/stalactite_4.json"),
BetterEnd.makeID("patterns/block/stalactite_5.json"),
BetterEnd.makeID("patterns/block/stalactite_6.json"),
BetterEnd.makeID("patterns/block/stalactite_7.json")
};
//Models Item
public final static Identifier ITEM_WALL = BetterEnd.makeID("patterns/item/pattern_wall.json");
public final static Identifier ITEM_FENCE = BetterEnd.makeID("patterns/item/pattern_fence.json");

View file

@ -107,6 +107,7 @@ import ru.betterend.blocks.basis.EndUnderwaterWallPlantBlock;
import ru.betterend.blocks.basis.EndWallPlantBlock;
import ru.betterend.blocks.basis.FurBlock;
import ru.betterend.blocks.basis.SimpleLeavesBlock;
import ru.betterend.blocks.basis.StalactiteBlock;
import ru.betterend.blocks.basis.StoneLanternBlock;
import ru.betterend.blocks.basis.VineBlock;
import ru.betterend.blocks.basis.WallMushroomBlock;
@ -177,6 +178,8 @@ public class EndBlocks {
public static final Block DENSE_EMERALD_ICE = registerBlock("dense_emerald_ice", new DenseEmeraldIceBlock());
public static final Block ANCIENT_EMERALD_ICE = registerBlock("ancient_emerald_ice", new AncientEmeraldIceBlock());
public static final Block END_STONE_STALACTITE = registerBlock("end_stone_stalactite", new StalactiteBlock(Blocks.END_STONE));
// Wooden Materials And Trees //
public static final Block MOSSY_GLOWSHROOM_SAPLING = registerBlock("mossy_glowshroom_sapling", new MossyGlowshroomSaplingBlock());
public static final Block MOSSY_GLOWSHROOM_CAP = registerBlock("mossy_glowshroom_cap", new MossyGlowshroomCapBlock());

View file

@ -5,6 +5,7 @@ import java.util.function.Supplier;
import com.google.common.collect.Lists;
import net.minecraft.block.Blocks;
import net.minecraft.util.Identifier;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStep;
@ -45,9 +46,10 @@ import ru.betterend.world.features.terrain.GeyserFeature;
import ru.betterend.world.features.terrain.IceStarFeature;
import ru.betterend.world.features.terrain.ObsidianBoulderFeature;
import ru.betterend.world.features.terrain.ObsidianPillarBasementFeature;
import ru.betterend.world.features.terrain.SingleBlockFeature;
import ru.betterend.world.features.terrain.SmaragdantCrystalFeature;
import ru.betterend.world.features.terrain.SmaragdantCrystalShardFeature;
import ru.betterend.world.features.terrain.SpireFeature;
import ru.betterend.world.features.terrain.StalactiteFeature;
import ru.betterend.world.features.terrain.SulphurHillFeature;
import ru.betterend.world.features.terrain.SulphuricCaveFeature;
import ru.betterend.world.features.terrain.SulphuricLakeFeature;
@ -191,8 +193,12 @@ public class EndFeatures {
// Caves
public static final DefaultFeature SMARAGDANT_CRYSTAL = new SmaragdantCrystalFeature();
public static final DefaultFeature SMARAGDANT_CRYSTAL_SHARD = new SmaragdantCrystalShardFeature();
public static final DefaultFeature SMARAGDANT_CRYSTAL_SHARD = new SingleBlockFeature(EndBlocks.SMARAGDANT_CRYSTAL_SHARD);
public static final DefaultFeature BIG_AURORA_CRYSTAL = new BigAuroraCrystalFeature();
public static final DefaultFeature CAVE_BUSH = new BushFeature(EndBlocks.CAVE_BUSH, EndBlocks.CAVE_BUSH);
public static final DefaultFeature CAVE_GRASS = new SingleBlockFeature(EndBlocks.CAVE_GRASS);
public static final DefaultFeature END_STONE_STALACTITE = new StalactiteFeature(true, EndBlocks.END_STONE_STALACTITE, Blocks.END_STONE);
public static final DefaultFeature END_STONE_STALAGMITE = new StalactiteFeature(false, EndBlocks.END_STONE_STALACTITE, Blocks.END_STONE);
public static void registerBiomeFeatures(Identifier id, Biome biome, List<List<Supplier<ConfiguredFeature<?, ?>>>> features) {
if (id.getNamespace().equals(BetterEnd.MOD_ID)) {

View file

@ -18,6 +18,7 @@ import ru.betterend.particle.ParticleSnowflake;
import ru.betterend.particle.ParticleSulphur;
import ru.betterend.particle.ParticleTenaneaPetal;
import ru.betterend.particle.PaticlePortalSphere;
import ru.betterend.particle.SmaragdantParticle;
public class EndParticles {
public static final DefaultParticleType GLOWING_SPHERE = register("glowing_sphere");
@ -31,6 +32,7 @@ public class EndParticles {
public static final DefaultParticleType TENANEA_PETAL = register("tenanea_petal");
public static final DefaultParticleType JUNGLE_SPORE = register("jungle_spore");
public static final DefaultParticleType FIREFLY = register("firefly");
public static final DefaultParticleType SMARAGDANT = register("smaragdant_particle");
public static void register() {
ParticleFactoryRegistry.getInstance().register(GLOWING_SPHERE, ParticleGlowingSphere.FactoryGlowingSphere::new);
@ -44,6 +46,7 @@ public class EndParticles {
ParticleFactoryRegistry.getInstance().register(TENANEA_PETAL, ParticleTenaneaPetal.FactoryTenaneaPetal::new);
ParticleFactoryRegistry.getInstance().register(JUNGLE_SPORE, ParticleJungleSpore.FactoryJungleSpore::new);
ParticleFactoryRegistry.getInstance().register(FIREFLY, FireflyParticle.FireflyParticleFactory::new);
ParticleFactoryRegistry.getInstance().register(SMARAGDANT, SmaragdantParticle.SmaragdantParticleFactory::new);
}
private static DefaultParticleType register(String name) {

View file

@ -24,6 +24,7 @@ import net.minecraft.world.WorldAccess;
import ru.betterend.blocks.BlueVineBlock;
import ru.betterend.blocks.basis.DoublePlantBlock;
import ru.betterend.blocks.basis.FurBlock;
import ru.betterend.blocks.basis.StalactiteBlock;
import ru.betterend.blocks.basis.VineBlock;
import ru.betterend.registry.EndBlocks;
import ru.betterend.registry.EndTags;
@ -207,6 +208,24 @@ public class BlocksHelper {
}
}
}
else if (state.getBlock() instanceof StalactiteBlock) {
if (!state.canPlaceAt(world, POS)) {
if (world.getBlockState(POS.up()).getBlock() instanceof StalactiteBlock) {
while (state.getBlock() instanceof StalactiteBlock) {
setWithoutUpdate(world, POS, AIR);
POS.setY(POS.getY() + 1);
state = world.getBlockState(POS);
}
}
else {
while (state.getBlock() instanceof StalactiteBlock) {
setWithoutUpdate(world, POS, AIR);
POS.setY(POS.getY() - 1);
state = world.getBlockState(POS);
}
}
}
}
else if (!state.canPlaceAt(world, POS)) {
// Chorus
if (state.isOf(Blocks.CHORUS_PLANT)) {

View file

@ -14,11 +14,19 @@ public class EmptyAuroraCaveBiome extends EndCaveBiome {
.setWaterAndFogColor(186, 77, 237)
.setMusic(EndSounds.MUSIC_FOREST)
.setParticles(EndParticles.GLOWING_SPHERE, 0.001F));
this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1);
this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1);
}
@Override
public float getFloorDensity() {
return 0.01F;
}
@Override
public float getCeilDensity() {
return 0.1F;
}
}

View file

@ -1,5 +1,6 @@
package ru.betterend.world.biome.cave;
import ru.betterend.registry.EndFeatures;
import ru.betterend.registry.EndSounds;
import ru.betterend.world.biome.land.BiomeDefinition;
@ -8,5 +9,18 @@ public class EmptyEndCaveBiome extends EndCaveBiome {
super(new BiomeDefinition("empty_end_cave")
.setFogDensity(2.0F)
.setMusic(EndSounds.MUSIC_FOREST));
this.addFloorFeature(EndFeatures.END_STONE_STALAGMITE, 1);
this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1);
}
@Override
public float getFloorDensity() {
return 0.1F;
}
@Override
public float getCeilDensity() {
return 0.1F;
}
}

View file

@ -13,13 +13,21 @@ public class EmptySmaragdantCaveBiome extends EndCaveBiome {
.setPlantsColor(0, 131, 145)
.setWaterAndFogColor(31, 167, 212)
.setMusic(EndSounds.MUSIC_FOREST)
.setParticles(EndParticles.FIREFLY, 0.001F));
.setParticles(EndParticles.SMARAGDANT, 0.001F));
this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1);
this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL_SHARD, 20);
this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1);
}
@Override
public float getFloorDensity() {
return 0.1F;
}
@Override
public float getCeilDensity() {
return 0.1F;
}
}

View file

@ -34,4 +34,8 @@ public class EndCaveBiome extends EndBiome {
public float getFloorDensity() {
return 0;
}
public float getCeilDensity() {
return 0;
}
}

View file

@ -16,11 +16,21 @@ public class LushAuroraCaveBiome extends EndCaveBiome {
.setMusic(EndSounds.MUSIC_FOREST)
.setParticles(EndParticles.GLOWING_SPHERE, 0.001F)
.setSurface(EndBlocks.CAVE_MOSS));
this.addFloorFeature(EndFeatures.BIG_AURORA_CRYSTAL, 1);
this.addFloorFeature(EndFeatures.CAVE_BUSH, 10);
this.addFloorFeature(EndFeatures.CAVE_GRASS, 40);
this.addCeilFeature(EndFeatures.CAVE_BUSH, 1);
}
@Override
public float getFloorDensity() {
return 0.01F;
return 0.1F;
}
@Override
public float getCeilDensity() {
return 0.03F;
}
}

View file

@ -14,14 +14,22 @@ public class LushSmaragdantCaveBiome extends EndCaveBiome {
.setPlantsColor(0, 131, 145)
.setWaterAndFogColor(31, 167, 212)
.setMusic(EndSounds.MUSIC_FOREST)
.setParticles(EndParticles.FIREFLY, 0.001F)
.setParticles(EndParticles.SMARAGDANT, 0.001F)
.setSurface(EndBlocks.CAVE_MOSS));
this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL, 1);
this.addFloorFeature(EndFeatures.SMARAGDANT_CRYSTAL_SHARD, 20);
this.addCeilFeature(EndFeatures.END_STONE_STALACTITE, 1);
}
@Override
public float getFloorDensity() {
return 0.1F;
}
@Override
public float getCeilDensity() {
return 0.1F;
}
}

View file

@ -63,7 +63,12 @@ public class BushFeature extends DefaultFeature {
for (Direction d: Direction.values()) {
BlockPos p = pos.offset(d);
if (world.isAir(p)) {
BlocksHelper.setWithoutUpdate(world, p, leaves.getDefaultState().with(LeavesBlock.DISTANCE, 1));
if (leaves instanceof LeavesBlock) {
BlocksHelper.setWithoutUpdate(world, p, leaves.getDefaultState().with(LeavesBlock.DISTANCE, 1));
}
else {
BlocksHelper.setWithoutUpdate(world, p, leaves.getDefaultState());
}
}
}

View file

@ -2,27 +2,36 @@ package ru.betterend.world.features.terrain;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
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.EndBlocks;
import ru.betterend.registry.EndTags;
import ru.betterend.util.BlocksHelper;
import ru.betterend.world.features.DefaultFeature;
public class SmaragdantCrystalShardFeature extends DefaultFeature {
public class SingleBlockFeature extends DefaultFeature {
private final Block block;
public SingleBlockFeature(Block block) {
this.block = block;
}
@Override
public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) {
if (!world.getBlockState(pos.down()).isIn(EndTags.GEN_TERRAIN)) {
return false;
}
BlockState shard = EndBlocks.SMARAGDANT_CRYSTAL_SHARD.getDefaultState();
boolean waterlogged = !world.getFluidState(pos).isEmpty();
BlocksHelper.setWithoutUpdate(world, pos, shard.with(Properties.WATERLOGGED, waterlogged));
BlockState state = block.getDefaultState();
if (block.getStateManager().getProperty("waterlogged") != null) {
boolean waterlogged = !world.getFluidState(pos).isEmpty();
state = state.with(Properties.WATERLOGGED, waterlogged);
}
BlocksHelper.setWithoutUpdate(world, pos, state);
return true;
}

View file

@ -40,13 +40,8 @@ public class SmaragdantCrystalFeature extends DefaultFeature {
BlocksHelper.setWithoutUpdate(world, mut, crystal);
mut.setY(mut.getY() + 1);
}
if (random.nextBoolean()) {
boolean waterlogged = !world.getFluidState(mut).isEmpty();
BlocksHelper.setWithoutUpdate(world, mut, shard.with(Properties.WATERLOGGED, waterlogged));
}
else {
BlocksHelper.setWithoutUpdate(world, mut, crystal);
}
boolean waterlogged = !world.getFluidState(mut).isEmpty();
BlocksHelper.setWithoutUpdate(world, mut, shard.with(Properties.WATERLOGGED, waterlogged));
}
}
}

View file

@ -0,0 +1,68 @@
package ru.betterend.world.features.terrain;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos.Mutable;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import ru.betterend.blocks.basis.StalactiteBlock;
import ru.betterend.registry.EndTags;
import ru.betterend.util.BlocksHelper;
import ru.betterend.world.features.DefaultFeature;
public class StalactiteFeature extends DefaultFeature {
private final boolean ceiling;
private final Block[] ground;
private final Block block;
public StalactiteFeature(boolean ceiling, Block block, Block... ground) {
this.ceiling = ceiling;
this.ground = ground;
this.block = block;
}
@Override
public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) {
if (!isGround(world.getBlockState(ceiling ? pos.up() : pos.down()).getBlock())) {
return false;
}
Mutable mut = new Mutable().set(pos);
int height = random.nextInt(8);
int dir = ceiling ? -1 : 1;
boolean stalagnate = false;
for (int i = 1; i <= height; i++) {
mut.setY(pos.getY() + i * dir);
BlockState state = world.getBlockState(mut);
if (!state.isAir()) {
stalagnate = state.isIn(EndTags.GEN_TERRAIN);
height = i - 1;
break;
}
}
int center = stalagnate ? height >> 1 : 0;
for (int i = 0; i < height; i++) {
mut.setY(pos.getY() + i * dir);
int size = stalagnate ? MathHelper.abs(i - center) + 1 : height - i - 1;
BlocksHelper.setWithoutUpdate(world, mut, block.getDefaultState().with(StalactiteBlock.SIZE, size));
}
return true;
}
private boolean isGround(Block block) {
for (Block b : ground) {
if (b == block) {
return true;
}
}
return false;
}
}

View file

@ -52,23 +52,31 @@ public abstract class EndCaveFeature extends DefaultFeature {
Set<BlockPos> caveBlocks = generate(world, center, radius, random);
if (!caveBlocks.isEmpty()) {
if (biome != null) {
boolean fillFloor = biome.getFloorDensity() > 0;
boolean fillCeil = biome.getCeilDensity() > 0;
setBiomes(world, biome, caveBlocks);
Set<BlockPos> floorPositions = Sets.newHashSet();
Set<BlockPos> ceilPositions = Sets.newHashSet();
Mutable mut = new Mutable();
caveBlocks.forEach((bpos) -> {
mut.set(bpos);
if (world.getBlockState(mut).getMaterial().isReplaceable()) {
mut.setY(bpos.getY() - 1);
if (world.getBlockState(mut).isIn(EndTags.GEN_TERRAIN)) {
floorPositions.add(mut.toImmutable());
if (fillFloor || fillCeil) {
caveBlocks.forEach((bpos) -> {
mut.set(bpos);
if (world.getBlockState(mut).getMaterial().isReplaceable()) {
if (fillFloor) {
mut.setY(bpos.getY() - 1);
if (world.getBlockState(mut).isIn(EndTags.GEN_TERRAIN)) {
floorPositions.add(mut.toImmutable());
}
}
if (fillCeil) {
mut.setY(bpos.getY() + 1);
if (world.getBlockState(mut).isIn(EndTags.GEN_TERRAIN)) {
ceilPositions.add(mut.toImmutable());
}
}
}
mut.setY(bpos.getY() + 1);
if (world.getBlockState(mut).isIn(EndTags.GEN_TERRAIN)) {
ceilPositions.add(mut.toImmutable());
}
}
});
});
}
BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceConfig().getTopMaterial();
placeFloor(world, biome, floorPositions, random, surfaceBlock);
placeCeil(world, biome, ceilPositions, random);
@ -100,7 +108,17 @@ public abstract class EndCaveFeature extends DefaultFeature {
}
protected void placeCeil(StructureWorldAccess world, EndCaveBiome biome, Set<BlockPos> ceilPositions, Random random) {
float density = biome.getCeilDensity();
if (density > 0) {
ceilPositions.forEach((pos) -> {
if (random.nextFloat() <= density) {
Feature<?> feature = biome.getCeilFeature(random);
if (feature != null) {
feature.generate(world, null, random, pos.down(), null);
}
}
});
}
}
protected void setBiomes(StructureWorldAccess world, EndCaveBiome biome, Set<BlockPos> blocks) {