Jump to content

[SOLVED] [1.14.2] custom tree does not replace sapling


mmyron

Recommended Posts

I have a custom tree that is not replacing the sapling when it spawns, and instead forms over the sapling leaving the sapling at the bottom.

 

Code:

Custom Sapling:

package com.mmyron.bettergameplay.block;

import com.mmyron.bettergameplay.block.tree.TallBirchTree;

import net.minecraft.block.SaplingBlock;

public class TallBirchSaplingBlock extends SaplingBlock{

	public TallBirchSaplingBlock(Properties properties) {
		super(new TallBirchTree(), properties);
	}

}

 

Tree:

package com.mmyron.bettergameplay.block.tree;

import java.util.Random;

import com.mmyron.bettergameplay.world.gen.feature.TallBirchTreeFeature;

import net.minecraft.block.trees.Tree;
import net.minecraft.world.gen.feature.AbstractTreeFeature;
import net.minecraft.world.gen.feature.NoFeatureConfig;

public class TallBirchTree extends Tree{
	@Override
	protected AbstractTreeFeature<NoFeatureConfig> getTreeFeature(Random random){
		return new TallBirchTreeFeature(NoFeatureConfig::func_214639_a, true);
	}
}

 

TreeFeature:

package com.mmyron.bettergameplay.world.gen.feature;

import java.util.Random;
import java.util.Set;
import java.util.function.Function;

import com.mmyron.bettergameplay.init.BlockList;
import com.mojang.datafixers.Dynamic;

import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.LogBlock;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.gen.IWorldGenerationReader;
import net.minecraft.world.gen.feature.AbstractTreeFeature;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraftforge.common.IPlantable;

public class TallBirchTreeFeature extends AbstractTreeFeature<NoFeatureConfig>{

	private BlockState blockStateWood = Blocks.OAK_LOG.getDefaultState();
	private BlockState blockStateLeaves = Blocks.OAK_LEAVES.getDefaultState();
	private final int minTreeHeight = 12;
	
	public TallBirchTreeFeature(Function<Dynamic<?>, ? extends NoFeatureConfig> dynamic, boolean notify) {
		super(dynamic, notify);
		// TODO Auto-generated constructor stub
	}
	
	private void generateLeaves(IWorld parWorld, BlockPos parBlockPos, int height, Random parRandom) {
		for (int foliageY = parBlockPos.getY() - 4 + height; foliageY <= parBlockPos.getY() + height; ++foliageY)
        {
            int foliageLayer = foliageY - (parBlockPos.getY() + height) - 2;
            int foliageLayerRadius = 0 - foliageLayer / 2;

            for (int foliageX = parBlockPos.getX() - foliageLayerRadius; foliageX <= parBlockPos.getX() + foliageLayerRadius; ++foliageX)
            {
                int foliageRelativeX = foliageX - parBlockPos.getX();
                
                for (int foliageZ = parBlockPos.getZ() - foliageLayerRadius; foliageZ <= parBlockPos.getZ() + foliageLayerRadius; ++foliageZ)
                {
                    int foliageRelativeZ = foliageZ - parBlockPos.getZ();

                    // Fill in layer with some randomness
                    if (Math.abs(foliageRelativeX) != foliageLayerRadius || Math.abs(foliageRelativeZ) != foliageLayerRadius || parRandom.nextInt(2) != 0 && foliageLayer != 0)
                    {
                        BlockPos blockPos = new BlockPos(foliageX, foliageY, foliageZ);
                        BlockState state = parWorld.getBlockState(blockPos);

                        if (state.getBlock().isAir(state, parWorld, blockPos) || state.getBlock() == Blocks.OAK_LOG)
                        {
                            this.setBlockState(parWorld, blockPos, blockStateLeaves);
                        }
                    }
                }
            }
        }
	}
	
	private void generateTrunk(IWorld worldIn, BlockPos parBlockPos, int minHeight)
    {
		for(int height = 0; height < minTreeHeight; ++height) {
			BlockPos upN = parBlockPos.up(height);
			BlockState state = worldIn.getBlockState(upN);
			
			if(state.getBlock().isAir(state, worldIn, upN) || state.getBlock() == Blocks.OAK_LEAVES || state.getBlock() == BlockList.Register.TALL_BIRCH_SAPLING) {
				this.setBlockState(worldIn, parBlockPos.up(height), blockStateWood.with(LogBlock.AXIS, Direction.Axis.Y));
			}
		}
    }
	
	private boolean isSuitableLocation(IWorldGenerationReader worldIn, BlockPos parBlockPos, int minHeight)
    {
        boolean isSuitableLocation = true;
        
        for (int checkY = parBlockPos.getY(); checkY <= parBlockPos.getY() + 1 + minHeight; ++checkY)
        {
            // Handle increasing space towards top of tree
            int extraSpaceNeeded = 1;
            // Handle base location
            if (checkY == parBlockPos.getY())
            {
                extraSpaceNeeded = 0;
            }             
            // Handle top location
            if (checkY >= parBlockPos.getY() + 1 + minHeight - 2)
            {
                extraSpaceNeeded = 2;
            }

            for (int checkX = parBlockPos.getX() - extraSpaceNeeded; checkX <= parBlockPos.getX() + extraSpaceNeeded && isSuitableLocation; ++checkX)
            {
                for (int checkZ = parBlockPos.getZ() - extraSpaceNeeded; checkZ <= parBlockPos.getZ() + extraSpaceNeeded && isSuitableLocation; ++checkZ)
                {
                    isSuitableLocation = /*isReplaceable(worldIn,blockPos.setPos(checkX, checkY, checkZ))*/ true;
                }
            }
        }
        
        return isSuitableLocation;
    }
	
	@Override
	protected boolean place(Set<BlockPos> changedBlocks, IWorldGenerationReader worldIn, Random random, BlockPos pos, MutableBoundingBox p_208519_5_) {
		int minHeight = random.nextInt(3) + minTreeHeight;
        
        if (pos.getY() >= 1 && pos.getY() + minHeight + 1 <= 256)
        {
            if (!isSuitableLocation(worldIn, pos, minHeight))
            {
                return false;
            }
            else
            {
                BlockState state = ((IBlockReader) worldIn).getBlockState(pos.down());

                if (state.getBlock().canSustainPlant(state, (IBlockReader) worldIn, pos.down(), Direction.UP, (IPlantable) BlockList.Register.TALL_BIRCH_SAPLING) && pos.getY() < 256 - minHeight - 1)
                {
                    state.getBlock().onPlantGrow(state, (IWorld) worldIn, pos.down(), pos);
                    generateLeaves((IWorld) worldIn, pos, minHeight, random);
                    generateTrunk((IWorld) worldIn, pos, minHeight);
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        else
        {
            return false;
        }
	}

}

 

Link to comment
Share on other sites

I have had this problem too. I've tried a lot of things, and for some reason it seems that the sapling can't be replaced by other blocks even if canBeReplacedByLogs returns true.

 

Edit: I did some more testing and found something sort of weird.

 

When I add

	@Override
	public void grow(IWorld worldIn, BlockPos pos, BlockState state, Random rand) {
		super.grow(worldIn, pos, state, rand);
		worldIn.setBlockState(pos, RevampBlocks.Register.MAPLE_LOG.getDefaultState().with(BlockMapleLog.SAP, true), 1|2);
	}

to my custom sapling block class, it replaces the sapling with a log but doesn't grow the tree. However, when I have

	@Override
	public void grow(IWorld worldIn, BlockPos pos, BlockState state, Random rand) {
		worldIn.setBlockState(pos, RevampBlocks.Register.MAPLE_LOG.getDefaultState().with(BlockMapleLog.SAP, true), 1|2);
		super.grow(worldIn, pos, state, rand);
	}

instead, it grows the tree but doesn't replace the sapling.

Edited by Guest
Link to comment
Share on other sites

  • mmyron changed the title to [SOLVED] [1.14.2] custom tree does not replace sapling

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.