package net.minecraft.world.level.levelgen.feature.foliageplacers; import com.mojang.datafixers.Products.P3; import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; import com.mojang.serialization.codecs.RecordCodecBuilder.Mu; import net.minecraft.util.RandomSource; import net.minecraft.util.valueproviders.IntProvider; import net.minecraft.world.level.LevelSimulatedReader; import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; public class BlobFoliagePlacer extends FoliagePlacer { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> blobParts(instance).apply(instance, BlobFoliagePlacer::new)); protected final int height; protected static

P3, IntProvider, IntProvider, Integer> blobParts(Instance

instance) { return foliagePlacerParts(instance).and(Codec.intRange(0, 16).fieldOf("height").forGetter(blobFoliagePlacer -> blobFoliagePlacer.height)); } public BlobFoliagePlacer(IntProvider radius, IntProvider offset, int height) { super(radius, offset); this.height = height; } @Override protected FoliagePlacerType type() { return FoliagePlacerType.BLOB_FOLIAGE_PLACER; } @Override protected void createFoliage( LevelSimulatedReader level, FoliagePlacer.FoliageSetter blockSetter, RandomSource random, TreeConfiguration config, int maxFreeTreeHeight, FoliagePlacer.FoliageAttachment attachment, int foliageHeight, int foliageRadius, int offset ) { for (int i = offset; i >= offset - foliageHeight; i--) { int j = Math.max(foliageRadius + attachment.radiusOffset() - 1 - i / 2, 0); this.placeLeavesRow(level, blockSetter, random, config, attachment.pos(), j, i, attachment.doubleTrunk()); } } @Override public int foliageHeight(RandomSource random, int height, TreeConfiguration config) { return this.height; } @Override protected boolean shouldSkipLocation(RandomSource random, int localX, int localY, int localZ, int range, boolean large) { return localX == range && localZ == range && (random.nextInt(2) == 0 || localY == 0); } }