Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
at master 103 lines 4.8 kB view raw
1package net.lerariemann.infinity.features; 2 3import com.mojang.serialization.Codec; 4import com.mojang.serialization.codecs.RecordCodecBuilder; 5import net.minecraft.core.BlockPos; 6import net.minecraft.core.Direction; 7import net.minecraft.tags.BlockTags; 8import net.minecraft.util.RandomSource; 9import net.minecraft.world.level.LevelAccessor; 10import net.minecraft.world.level.WorldGenLevel; 11import net.minecraft.world.level.block.state.BlockState; 12import net.minecraft.world.level.levelgen.feature.Feature; 13import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; 14import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; 15import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; 16 17public abstract class RandomMushroomFeature 18 extends Feature<RandomMushroomFeature.Config> { 19 public RandomMushroomFeature(Codec<Config> codec) { 20 super(codec); 21 } 22 23 protected void generateStem(LevelAccessor world, RandomSource random, BlockPos pos, Config config, int height, BlockPos.MutableBlockPos mutablePos) { 24 for (int i = 0; i < height; ++i) { 25 mutablePos.set(pos).move(Direction.UP, i); 26 if (world.getBlockState(mutablePos).isSolidRender( 27 //? if <1.21.2 28 /*world, mutablePos*/ 29 )) continue; 30 this.setBlock(world, mutablePos, config.stemProvider().getState(random, pos)); 31 } 32 } 33 34 protected int getHeight(RandomSource random, int h) { 35 int i = random.nextInt(3) + h - 1; 36 if (random.nextInt(12) == 0) { 37 i *= 2; 38 } 39 return i; 40 } 41 42 protected boolean canGenerate(LevelAccessor world, BlockPos pos, int height, BlockPos.MutableBlockPos mutablePos, Config config) { 43 int i = pos.getY(); 44 //? if <1.21.2 { 45 /*var minY = world.getMinBuildHeight(); 46 var maxY = world.getMaxBuildHeight(); 47 *///?} else { 48 var minY = world.getMinY(); 49 var maxY = world.getMaxY(); 50 //?} 51 if (i < minY + 1 || i + height + 1 >= maxY) { 52 return false; 53 } 54 BlockState blockState = world.getBlockState(pos.below()); 55 if (!blockState.getBlock().equals(config.validBaseBlock().getBlock())) { 56 return false; 57 } 58 for (int j = 0; j <= height; ++j) { 59 int k = this.getCapSize(-1, -1, config.foliageRadius(), j); 60 for (int l = -k; l <= k; ++l) { 61 for (int m = -k; m <= k; ++m) { 62 BlockState blockState2 = world.getBlockState(mutablePos.setWithOffset(pos, l, j, m)); 63 if (blockState2.isAir() || blockState2.is(BlockTags.LEAVES)) continue; 64 return false; 65 } 66 } 67 } 68 return true; 69 } 70 71 @Override 72 public boolean place(FeaturePlaceContext<Config> context) { 73 BlockPos.MutableBlockPos mutable; 74 WorldGenLevel structureWorldAccess = context.level(); 75 BlockPos blockPos = context.origin(); 76 RandomSource random = context.random(); 77 Config hugeMushroomFeatureConfig = context.config(); 78 int i = this.getHeight(random, context.config().height()); 79 if (!this.canGenerate(structureWorldAccess, blockPos, i, mutable = new BlockPos.MutableBlockPos(), hugeMushroomFeatureConfig)) { 80 return false; 81 } 82 this.generateCap(structureWorldAccess, random, blockPos, i, mutable, hugeMushroomFeatureConfig); 83 this.generateStem(structureWorldAccess, random, blockPos, hugeMushroomFeatureConfig, i, mutable); 84 return true; 85 } 86 87 protected abstract int getCapSize(int var1, int var2, int var3, int var4); 88 89 protected abstract void generateCap(LevelAccessor var1, RandomSource var2, BlockPos var3, int var4, BlockPos.MutableBlockPos var5, Config var6); 90 91 public record Config(BlockStateProvider capProvider, BlockStateProvider stemProvider, 92 BlockState validBaseBlock, int foliageRadius, 93 int height) implements FeatureConfiguration { 94 public static final Codec<Config> CODEC = RecordCodecBuilder.create(instance -> instance.group( 95 (BlockStateProvider.CODEC.fieldOf("cap_provider")).forGetter(a -> a.capProvider), 96 (BlockStateProvider.CODEC.fieldOf("stem_provider")).forGetter(a -> a.stemProvider), 97 (BlockState.CODEC.fieldOf("valid_base_block")).forGetter(a -> a.validBaseBlock), 98 (Codec.INT.fieldOf("foliage_radius")).orElse(2).forGetter(a -> a.foliageRadius), 99 (Codec.INT.fieldOf("height")).orElse(5).forGetter(a -> a.height)).apply( 100 instance, Config::new)); 101 } 102} 103