Jump to content

Recommended Posts

Posted

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;
        }
	}

}

 

Posted (edited)

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
Posted

I found a solution: you can use the BirchTreeFeature code as a template.

  • 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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I also just tried with iron's spellbooks removed, since that seemed related, but i am still having the same problem, even in newly created worlds. https://mclo.gs/AtrAfaj 
    • My Gradle Project for my Minecraft mod isn't building. Terminal: * Where: Settings file 'C:\Users\csonn\OneDrive\Desktop\fusionlucky\settings.gradle' line: 2 * What went wrong: Could not compile settings file 'C:\Users\csonn\OneDrive\Desktop\fusionlucky\settings.gradle'. > startup failed:   settings file 'C:\Users\csonn\OneDrive\Desktop\fusionlucky\settings.gradle': 2: The pluginManagement {} block must appear before any other statements in the script.   For more information on the pluginManagement {} block, please refer to https://docs.gradle.org/9.0.0/userguide/plugins.html#sec:plugin_management in the Gradle documentation.    @ line 2, column 1.      pluginManagement {      ^   1 error * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to generate a Build Scan (Powered by Develocity). > Get more help at https://help.gradle.org.   Setting.Gradle File:   rootProject.name = 'fusion-lucky-block' pluginManagement {     repositories {         gradlePluginPortal()         maven { url "https://maven.minecraftforge.net/" }         mavenCentral()     } }
    • no change still. here's a new log  https://mclo.gs/RXwiZmn 
    • Whenever I go to build my it says "Build failed in " how many seconds   Here is what is said in my terminal * Where: Build file 'C:\Users\csonn\OneDrive\Desktop\fusionlucky\build.gradle' line: 3 * What went wrong: Plugin [id: 'net.minecraftforge.gradle', version: '6.1.51'] was not found in any of the following sources: - Gradle Core Plugins (plugin is not in 'org.gradle' namespace) - Included Builds (No included builds contain this plugin) - Plugin Repositories (could not resolve plugin artifact 'net.minecraftforge.gradle:net.minecraftforge.gradle.gradle.plugin:6.1.51')   Searched in the following repositories:     Gradle Central Plugin Repository     MinecraftForge(https://maven.minecraftforge.net/) * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Get more help at https://help.gradle.org.   Here is what is in my build.gradle file plugins {     id 'java'     id 'net.minecraftforge.gradle' version '6.1+' }   group = 'io.github.csonnic03.fusionlucky' version = '1.0.0' archivesBaseName = 'fusionlucky'   java {     toolchain {         languageVersion = JavaLanguageVersion.of(17)     } }   repositories {     mavenCentral()     maven {         name "forgeMaven"         url "https://maven.minecraftforge.net/<repository>" } }   dependencies {     minecraft 'net.minecraftforge:forge:1.20.1-47.1.0' }   minecraft {     mappings channel: 'official', version: '1.20.1'     runs {         client {             workingDirectory project.file('run')         }         server {             workingDirectory project.file('run')         }     } }   tasks.withType(JavaCompile) {     options.encoding = 'UTF-8' }   jar {     manifest {         attributes(             "Specification-Title": "Fusion Lucky Block",             "Specification-Vendor": "example",             "Implementation-Title": project.name,             "Implementation-Version": project.version,             "Implementation-Vendor": "example",             "ModLauncher-TargetFMLVersion": "[47,)"         )     } }  
  • Topics

×
×
  • Create New...

Important Information

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