package net.minecraft.world.level.levelgen.feature.foliageplacers; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; 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 SpruceFoliagePlacer extends FoliagePlacer { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> foliagePlacerParts(instance) .and(IntProvider.codec(0, 24).fieldOf("trunk_height").forGetter(spruceFoliagePlacer -> spruceFoliagePlacer.trunkHeight)) .apply(instance, SpruceFoliagePlacer::new) ); private final IntProvider trunkHeight; public SpruceFoliagePlacer(IntProvider radius, IntProvider offset, IntProvider trunkHeight) { super(radius, offset); this.trunkHeight = trunkHeight; } @Override protected FoliagePlacerType type() { return FoliagePlacerType.SPRUCE_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 ) { BlockPos blockPos = attachment.pos(); int i = random.nextInt(2); int j = 1; int k = 0; for (int l = offset; l >= -foliageHeight; l--) { this.placeLeavesRow(level, blockSetter, random, config, blockPos, i, l, attachment.doubleTrunk()); if (i >= j) { i = k; k = 1; j = Math.min(j + 1, foliageRadius + attachment.radiusOffset()); } else { i++; } } } @Override public int foliageHeight(RandomSource random, int height, TreeConfiguration config) { return Math.max(4, height - this.trunkHeight.sample(random)); } @Override protected boolean shouldSkipLocation(RandomSource random, int localX, int localY, int localZ, int range, boolean large) { return localX == range && localZ == range && range > 0; } }