Как создать свое дерево?

Версия Minecraft
1.12.2
Как создать свое дерево которое будет расти из саженца? Покажите пожалуйста все классы которые нужны для этого, что за что отвечает. (Ссылки на видео не нужны, я всех их пересмотрел и нифига не понял..)
 
31
2
Как создать свое дерево которое будет расти из саженца? Покажите пожалуйста все классы которые нужны для этого, что за что отвечает. (Ссылки на видео не нужны, я всех их пересмотрел и нифига не понял..)
BlockSapling, BlockLog, BlockLeaves, (BlockLeavesBase)
 
683
3
21
1,057
50
234
public static final IBlockState LOG = BlockInit.LOGS.getDefaultState().withProperty(BlockLogs.VARIANT, EnumHandler.EnumType.COPPER);
public static final IBlockState LEAF = BlockInit.LEAVES.getDefaultState().withProperty(BlockLeaf.VARIANT, EnumHandler.EnumType.COPPER);

Это как-бы и есть блоки. Настраиваются в твоем WorldGen
 
917
22
332
Ты задаёшь вопрос, но при этом со своей стороны не дал даже направления в котором нужно двигаться. Серьёзно. Если ты действительно пытался что-либо сделать, ты мог бы выложить свои наработки (код). Но с нуля довольно большой рабочий код тебе, скорее всего, никто не напишет. Это не коммерческий раздел, и мы тоже люди.
  • Ты можешь найти исходники модов в которых есть деревья. Скопировать их и подработать под себя.
  • Попытаться скопировать ванильные классы, и начать исправлять ошибки. И выложить свой код здесь. Тогда тебе смогут помогать несколько людей понемногу. И шанс, что ты решишь свой проблему значительно возрастёт.
 
Вообщем, мне удалось создать дерево, но саженец неправильно отображается и вместо заданных блоков генерируется обычный дуб, установил всё как надо, а оно все равно регенет дуб

Код:
    public static final IBlockState LOG = BlockInit.LINDENLOG.getDefaultState().withProperty(BlockLogs.VARIANT, EnumHandler.EnumType.LINDEN);
    public static final IBlockState LEAF = BlockInit.LINDENLEAF.getDefaultState().withProperty(BlockLeaf.VARIANT, EnumHandler.EnumType.LINDEN);
 
Скинь код своего генератора.

Код:
public class LindenTree extends WorldGenAbstractTree
{
    public static final IBlockState LOG = BlockInit.LINDENLOG.getDefaultState().withProperty(BlockLogs.VARIANT, EnumHandler.EnumType.LINDEN);
    public static final IBlockState LEAF = BlockInit.LINDENLEAF.getDefaultState().withProperty(BlockLeaf.VARIANT, EnumHandler.EnumType.LINDEN);
    
    private final int minHeight;
    
    public LindenTree()
    {
        super(false);
        this.minHeight = 12;
    }

    @Override
    public boolean generate(World world, Random rand, BlockPos pos)
    {
        int height = this.minHeight + rand.nextInt(3);
        boolean flag = true;
        
        int x = pos.getX();
        int y = pos.getY();
        int z = pos.getZ();
        
        for(int yPos = y; yPos <= y + 1 + height; yPos++)
        {
            int b0 = 2;
            if(yPos == y) b0 = 1;
            if(yPos >= y + 1 + height - 2) b0 = 2;
            
            for(int xPos = x - b0; xPos <= x + b0 && flag; xPos++)
            {
                for(int zPos = z - b0; zPos <- z + b0 && flag; zPos++)
                {
                    if(yPos >= 0 && yPos < world.getHeight())
                    {
                        if(!this.isReplaceable(world, new BlockPos(xPos, yPos, zPos)))
                        {
                            flag = false;
                        }
                    }
                    else
                    {
                        flag = false;
                    }
                }
            }
        }
        
        if(!flag)
        {
            return false;
        }
        else
        {
            BlockPos down = pos.down();
            IBlockState state = world.getBlockState(down);
            boolean isSoil = state.getBlock().canSustainPlant(state, world, down, EnumFacing.UP, (BlockSaplings)BlockInit.LINDENSAPLING);
            
            if(isSoil && y < world.getHeight() - height - 1)
            {
                state.getBlock().onPlantGrow(state, world, down, pos);
                
                for(int yPos = y - 3 + height; yPos <= y + height; yPos++)
                {
                    int b1 = yPos - (y + height);
                    int b2 = 1 - b1 / 2;
                    
                    for(int xPos = x - b2; xPos <= x + b2; xPos++)
                    {
                        int b3 = xPos - x;
                        for(int zPos = z - b2; zPos <= z + b2; zPos++)
                        {
                            int b4 = zPos - z;
                            if(Math.abs(b3) != b2 || Math.abs(b4) != b2 || rand.nextInt(2) != 0 && b1 != 0)
                            {
                                BlockPos treePos = new BlockPos(xPos, yPos, zPos);
                                IBlockState treeState = world.getBlockState(treePos);
                                if(treeState.getBlock().isAir(treeState, world, treePos) || treeState.getBlock().isAir(treeState, world, treePos))
                                {
                                    this.setBlockAndNotifyAdequately(world, treePos, LEAF);
                                    this.setBlockAndNotifyAdequately(world, treePos.add(0, -0.25 * height, 0), LEAF);
                                    this.setBlockAndNotifyAdequately(world, treePos.add(0, -0.5 * height, 0), LEAF);
                                }
                            }
                        }
                    }
                }
                
                for(int logHeight = 0; logHeight < height; logHeight++)
                {
                    BlockPos up = pos.up(logHeight);
                    IBlockState logState = world.getBlockState(up);
                    
                    if(logState.getBlock().isAir(logState, world, up) || logState.getBlock().isLeaves(logState, world, up))
                    {
                        this.setBlockAndNotifyAdequately(world, pos.up(logHeight), LOG);
                    }
                }
                
                return true;
            }
        }
        
        return true;
    }   
}
 
Выложи код саженца, код вот этого класса

Код:
public class BlockLogs extends BlockLog implements IMetaName, IHasModel
{
    public static final PropertyEnum<EnumHandler.EnumType> VARIANT = PropertyEnum.<EnumHandler.EnumType>create("variant", EnumHandler.EnumType.class, new Predicate<EnumHandler.EnumType>()
    {
        public boolean apply(@Nullable EnumHandler.EnumType apply)
        {
            return apply.getMeta() < 2;
        }
    });
    
    //private String name;
    
    public BlockLogs(String name)
    {
        setUnlocalizedName(name);
        setRegistryName(name);
        setSoundType(SoundType.WOOD);
        setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, EnumHandler.EnumType.LINDEN).withProperty(LOG_AXIS, EnumAxis.Y));
        setCreativeTab(TheScraGullWorld.BLOCKS);
        
        //this.name = name;
        
        BlockInit.BLOCKS.add(this);
        ItemInit.ITEMS.add(new ItemBlockVariants(this).setRegistryName(this.getRegistryName()));
    }
    
    @Override
    public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
    {
        for(EnumHandler.EnumType customblockplanks$enumtype : EnumHandler.EnumType.values())
        {
            items.add(new ItemStack(this, 1, customblockplanks$enumtype.getMeta()));
        }
    }
    
    @Override
    public IBlockState getStateFromMeta(int meta)
    {
        IBlockState state = this.getDefaultState().withProperty(VARIANT, EnumHandler.EnumType.byMetadata((meta & 1) % 2));
        
        switch(meta & 6)
        {
        case 0:
            state = state.withProperty(LOG_AXIS, EnumAxis.Y);
            break;
            
        case 2:
            state = state.withProperty(LOG_AXIS, EnumAxis.X);
            break;
            
        case 4:
            state = state.withProperty(LOG_AXIS, EnumAxis.Z);
            break;
            
        default:
            state = state.withProperty(LOG_AXIS, EnumAxis.NONE);
        }
        
        return state;
    }
    
    @SuppressWarnings("incomplete-switch")
    @Override
    public int getMetaFromState(IBlockState state)
    {
        int i = 0;
        i = i | ((EnumHandler.EnumType)state.getValue(VARIANT)).getMeta();
        
        switch((BlockLog.EnumAxis)state.getValue(LOG_AXIS))
        {
        case X:
            i |= 2;
            break;
            
        case Y:
            i |= 4;
            break;
            
        case Z:
            i |= 6;
        }
        
        return i;
    }
    
    @Override
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {VARIANT,LOG_AXIS});
    }
    
    @Override
    protected ItemStack getSilkTouchDrop(IBlockState state)
    {
        return new ItemStack(Item.getItemFromBlock(this), 1, ((EnumHandler.EnumType)state.getValue(VARIANT)).getMeta());
    }
    
    @Override
    public int damageDropped(IBlockState state)
    {
        return ((EnumHandler.EnumType)state.getValue(VARIANT)).getMeta();
    }
    
    @Override
    public String getSpecialName(ItemStack stack)
    {
        return EnumHandler.EnumType.values()[stack.getItemDamage()].getName();
    }
    
    @Override
    public void registerModels()
    {
        for(int i = 0; i < EnumHandler.EnumType.values().length; i++)
        {
            TheScraGullWorld.proxy.registerVariantRenderer(Item.getItemFromBlock(this), i, "log_" + EnumHandler.EnumType.values()[i].getName(), "inventory");
        }
    }   
}
 
Сверху