Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
at master 102 lines 5.0 kB view raw
1package net.lerariemann.infinity.features; 2 3import com.google.common.collect.ImmutableList; 4import com.mojang.serialization.MapCodec; 5import com.mojang.serialization.codecs.RecordCodecBuilder; 6import net.lerariemann.infinity.registry.core.ModFeatures; 7import net.minecraft.core.BlockPos; 8import net.minecraft.core.Direction; 9import net.minecraft.util.ExtraCodecs; 10import net.minecraft.util.RandomSource; 11import net.minecraft.world.level.LevelSimulatedReader; 12import net.minecraft.world.level.block.state.BlockState; 13import net.minecraft.world.level.block.state.properties.BlockStateProperties; 14import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; 15import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacer; 16import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacer; 17import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType; 18import java.util.List; 19import java.util.function.BiConsumer; 20import java.util.function.Function; 21 22public class WonkyTrunkPlacer extends TrunkPlacer { 23 public static final MapCodec<WonkyTrunkPlacer> CODEC = RecordCodecBuilder.mapCodec( 24 instance -> trunkPlacerParts(instance) 25 .and( 26 instance.group( 27 ExtraCodecs.POSITIVE_FLOAT.optionalFieldOf("weight_up", 1f).forGetter(a -> a.weightUp), 28 ExtraCodecs.POSITIVE_FLOAT.optionalFieldOf("weight_down", 0.1f).forGetter(a -> a.weightDown), 29 ExtraCodecs.POSITIVE_FLOAT.optionalFieldOf("weight_side", 0.5f).forGetter(a -> a.weightSide) 30 ) 31 ) 32 .apply(instance, WonkyTrunkPlacer::new)); 33 final float weightUp; 34 final float weightDown; 35 final float weightSide; 36 Direction currentDir; 37 38 public WonkyTrunkPlacer(int baseHeight, int firstRandomHeight, int secondRandomHeight, float weightUp, float weightDown, float weightSide) { 39 super(baseHeight, firstRandomHeight, secondRandomHeight); 40 this.weightUp = Math.max(weightUp, 1f); 41 this.weightDown = Math.max(weightDown, 1f); 42 this.weightSide = Math.max(weightDown, 1f); 43 currentDir = Direction.UP; 44 } 45 46 @Override 47 protected TrunkPlacerType<?> type() { 48 return ModFeatures.WONKY_TRUNK.get(); 49 } 50 51 @Override 52 public List<FoliagePlacer.FoliageAttachment> placeTrunk(LevelSimulatedReader world, BiConsumer<BlockPos, BlockState> replacer, RandomSource random, int height, BlockPos startPos, TreeConfiguration config) { 53 setDirtAt(world, replacer, random, startPos.below(), config); 54 BlockPos curr = startPos; 55 this.placeLog(world, replacer, random, startPos, config); 56 for (int i = 0; i < height; i++) { 57 double d = random.nextDouble() * (weightUp + weightDown + weightSide); 58 Direction dir; 59 if (d < weightUp) dir = Direction.UP; 60 else if (d < weightUp + weightDown) dir = Direction.DOWN; 61 else { 62 dir = switch (random.nextInt(4)) { 63 case 1 -> Direction.WEST; 64 case 2 -> Direction.EAST; 65 case 3 -> Direction.NORTH; 66 default -> Direction.SOUTH; 67 }; 68 } 69 if (!this.validTreePos(world, curr.relative(dir))) dir = Direction.UP; 70 curr = curr.relative(dir); 71 currentDir = dir; 72 this.placeLog(world, replacer, random, curr, config); 73 } 74 return ImmutableList.of(new FoliagePlacer.FoliageAttachment(curr, 0, false)); 75 } 76 77 @Override 78 79 80 protected boolean placeLog( 81 LevelSimulatedReader world, 82 BiConsumer<BlockPos, BlockState> replacer, 83 RandomSource random, 84 BlockPos pos, 85 TreeConfiguration config, 86 Function<BlockState, BlockState> function 87 ) { 88 if (this.validTreePos(world, pos)) { 89 BlockState bs = function.apply(config.trunkProvider.getState(random, pos)); 90 Direction.Axis axis = currentDir.getAxis(); 91 if (bs.hasProperty(BlockStateProperties.AXIS)) bs = bs.setValue(BlockStateProperties.AXIS, axis); 92 if (bs.hasProperty(BlockStateProperties.HORIZONTAL_AXIS) && axis.isHorizontal()) bs = bs.setValue(BlockStateProperties.HORIZONTAL_AXIS, axis); 93 if (bs.hasProperty(BlockStateProperties.FACING)) bs = bs.setValue(BlockStateProperties.FACING, currentDir); 94 if (bs.hasProperty(BlockStateProperties.HORIZONTAL_FACING) && axis.isHorizontal()) bs = bs.setValue(BlockStateProperties.HORIZONTAL_FACING, currentDir); 95 if (bs.hasProperty(BlockStateProperties.FACING_HOPPER) && currentDir != Direction.UP) bs = bs.setValue(BlockStateProperties.FACING_HOPPER, currentDir); 96 replacer.accept(pos, bs); 97 return true; 98 } else { 99 return false; 100 } 101 } 102}