Jump to content

Recommended Posts

Posted (edited)

There is something about DecoratedFeatureConfig.

It looks like, it get´s flowers to place, that came into the biome this way

But i don´know, how to get my tulips with DecoratedFeatureConfig into the biomes...

Actualy i use BlockClusterFeatureConfig.

Edited by Drachenbauer
Posted

Iow i found out, that ForestFlowerBlockStateProvider and PlainFlowerBlockStateProvider use blockstate-lists, wich include the vanilla-tulips.

 

Is there any way to pass my own list:

    private static final BlockState[] TULIPS_BLOCKSTATES = new BlockState[]
    {
        Blocks.RED_TULIP.getDefaultState(),
        Blocks.ORANGE_TULIP.getDefaultState(),
        Blocks.WHITE_TULIP.getDefaultState(),
        Blocks.PINK_TULIP.getDefaultState(),
        
        MoreTulipsBlocks.BLACK_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.BLUE_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.BROWN_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.CYAN_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.GRAY_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.GREEN_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.LIGHT_BLUE_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.LIGHT_GRAY_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.LIME_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.MAGENTA_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.PURPLE_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.YELLOW_TULIP.get().getDefaultState(),
    };

into theese providers or should i register my own BlockStateProvider

Posted

So I was looking at some vanilla code, and noticed if you trace back from GrassBlock, you see in the grow method that there's a call to a biome getFlowers(). If you look at that method, you see it returns the biome's flowers. In Eclipse, you can right click on a method, and select "Open Call Heirarchy". This shows places where this is accessed, and doing this to the flowers field in the biome, it shows me it's accessed in the addFeature method of Biome. THIS shows me when a feature is added via addFeature, if the feature is Feature.DECORATED_FLOWER, it adds that to the list of flowers.

 

Your feature is of type Feature.FLOWER. What happens if you change it?

 

I showed you my trail of thought/research, in hopes it will help you with backtracing through the code to find what you're looking for. Learn how to use the features of your IDE to help you. :)

Posted (edited)

I already used that backtracing and found, what you say, but i cannot find, where  DECORATED_FLOWER get´s the flowers from, and i found nothing there, where code in my own classes can access.

 

so i now create my own bonemeal, that manually adds my tulips, if the clicked grass-block is in one of the three vanilla-biomes with tulips.

I make it the way, how my bick blocks in the other mod add their invisible part-blocks to the world, if placed.

At first i let it find random positions in a 9x9 square around the clicked grass-blocks and find te surface of the ground there and then it should place random tulips there, if a grassblock is below and the position, itself has just air or a plant (but not a tree or a tulip).

It just needs a little bugfix and i think, i find the solution.

 

Edit:

I fixed it.

My custom bonemeal now makes alot of colorful tulips grow.

 

now i think, i can pack my mod.

 

But i have one last question:

How can i make the vanilla bonemeal use this behavior?

Edited by Drachenbauer
Posted

This is now my
custom bonemeal class:

Spoiler

package drachenbauer32.moretulipsmod.items;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

import drachenbauer32.moretulipsmod.init.MoreTulipsBlocks;
import net.minecraft.block.AirBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FlowerBlock;
import net.minecraft.block.GrassBlock;
import net.minecraft.block.IGrowable;
import net.minecraft.item.BoneMealItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.server.ServerWorld;

public class TulipsBoneMealItem extends BoneMealItem 
{
    private static final Biome[] BIOMES = new Biome[]
    {
        Biomes.PLAINS,
        Biomes.SUNFLOWER_PLAINS,
        Biomes.FLOWER_FOREST
    };
    
    private static final BlockState[] TULIPS_BLOCKSTATES = new BlockState[]
    {
        Blocks.RED_TULIP.getDefaultState(),
        Blocks.ORANGE_TULIP.getDefaultState(),
        Blocks.WHITE_TULIP.getDefaultState(),
        Blocks.PINK_TULIP.getDefaultState(),
        
        MoreTulipsBlocks.BLACK_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.BLUE_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.BROWN_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.CYAN_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.GRAY_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.GREEN_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.LIGHT_BLUE_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.LIGHT_GRAY_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.LIME_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.MAGENTA_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.PURPLE_TULIP.get().getDefaultState(),
        MoreTulipsBlocks.YELLOW_TULIP.get().getDefaultState(),
    };
    
    /**
     ** With this integer, the code stops searching for tulip-positions,
     ** if it fails 10 times in a row at the last method.
     ** so it cannot stuck in an infinite loop, if there are not enough
     ** valid locations around the clicked grassblock.
     **/
    private static int tries = 0;
    
    public TulipsBoneMealItem(Properties p_i50055_1_)
    {
        super(p_i50055_1_);
    }
    
    /**
     ** I copyed the whoole code of this method, because override with return super method
     ** makes it call the applyBonemeal method from the vanilla BoneMealItem and not the one from here.
     **/
    public ActionResultType onItemUse(ItemUseContext context)
    {
        World world = context.getWorld();
        BlockPos blockpos = context.getPos();
        BlockPos blockpos1 = blockpos.offset(context.getFace());
        
        if (applyBonemeal(context.getItem(), world, blockpos, context.getPlayer()))
        {
            if (!world.isRemote)
            {
                world.playEvent(2005, blockpos, 0);
            }
            
            return ActionResultType.SUCCESS;
        }
        else
        {
            BlockState blockstate = world.getBlockState(blockpos);
            boolean flag = blockstate.isSolidSide(world, blockpos, context.getFace());
            
            if (flag && growSeagrass(context.getItem(), world, blockpos1, context.getFace()))
            {
                if (!world.isRemote)
                {
                    world.playEvent(2005, blockpos1, 0);
                }
                
                return ActionResultType.SUCCESS;
            }
            else
            {
                return ActionResultType.PASS;
            }
        }
    }
    
    /**
     ** I placed the modification to check for specific biomes,
     ** and use the following methods, into a copy of the vanilla applyBonemeal-method,
     ** because it has a return-type and i cannot override static methods.
     **/
    public static boolean applyBonemeal(ItemStack stack, World worldIn, BlockPos pos, net.minecraft.entity.player.PlayerEntity player)
    {
        BlockState blockstate = worldIn.getBlockState(pos);
        int hook = net.minecraftforge.event.ForgeEventFactory.onApplyBonemeal(player, worldIn, pos, blockstate, stack);
        
        if (hook != 0)
        {
            return hook > 0;
        }
        
        if (blockstate.getBlock() instanceof IGrowable)
        {
            IGrowable igrowable = (IGrowable)blockstate.getBlock();
            if (igrowable.canGrow(worldIn, pos, blockstate, worldIn.isRemote))
            {
                if (worldIn instanceof ServerWorld)
                {
                    if (igrowable.canUseBonemeal(worldIn, worldIn.rand, pos, blockstate))
                    {
                        igrowable.grow((ServerWorld)worldIn, worldIn.rand, pos, blockstate);
                        
                        Biome biome = player.world.getBiome(pos);
                        
                        if(Arrays.asList(BIOMES).contains(biome))
                        {
                            int i = 0;
                                    
                            while (i < 2)
                            {
                                tries = 0;
                                findRandomPos(worldIn, pos);
                                i++;
                            }
                            
                            if(biome == Biomes.FLOWER_FOREST)
                            {
                                while (i < 10)
                                {
                                    tries = 0;
                                    findRandomPos(worldIn, pos);
                                    i++;
                                }
                            }
                        }
                    }
                    
                    stack.shrink(1);
                }
                
                
                return true;
            }
        }
        
        return false;
    }
    
    /**
     ** This method finds random positions on ground in a 9x9 square
     ** with the clicked Grassblock in the center.
     **/
    private static void findRandomPos(World worldIn, BlockPos pos)
    {
        BlockPos position = pos;
        
        int rnd_n_s = new Random().nextInt(9);
        int rnd_e_w = new Random().nextInt(9);
        
        position = position.north(rnd_n_s - 4);
        position = position.east(rnd_e_w - 4);
        
        while (worldIn.getBlockState(position).isOpaqueCube(worldIn, position))
        {
            position = position.up();
        }
        
        if (!canGrowTulips(worldIn, position))
        {
            while (!worldIn.getBlockState(position.down()).isOpaqueCube(worldIn, position.down()))
            {
                position = position.down();
            }
            
            if (!canGrowTulips(worldIn, position))
            {
                if (tries < 10)
                {
                    findRandomPos(worldIn, position);
                    tries++;
                }
            }
        }
    }
    
    /**
     ** this method places a random tulip,
     ** if the block below the passed position is a grassblock
     ** and at the posithon is air or a plant (but not a tree or a tulip).
     **/
    private static boolean canGrowTulips(World worldIn, BlockPos pos)
    {
        BlockState blockstate_1 = worldIn.getBlockState(pos.down());
        BlockState blockstate_2 = worldIn.getBlockState(pos);
        
        int rnd = new Random().nextInt(TULIPS_BLOCKSTATES.length);
        BlockState tulip_blockstate = TULIPS_BLOCKSTATES[rnd];
        
        if (blockstate_1.getBlock() instanceof GrassBlock && (blockstate_2.getBlock() instanceof AirBlock || blockstate_2.getBlock() instanceof FlowerBlock))
        {
            if (Arrays.asList(TULIPS_BLOCKSTATES).contains(blockstate_2))
            {
                return false;
            }
            
            worldIn.setBlockState(pos, tulip_blockstate);
            worldIn.setBlockState(pos.up(), Blocks.AIR.getDefaultState());
            return true;
        }
        else
        {
            return false;
        }
    }
}

How can i make the vanilla BoneMealItem-class use my custom methods and the custom added part of the applyBonemeal-method here after it´s normal rightclick-behavior?

 

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

    • The game crashed whilst unexpected error Error: net.minecraftforge.fml.ModLoadingException: Advanced Mining Dimension (mining_dimension) encountered an error during the done event phase
    • Here is the end of the log. it was way too big to put in pastebin, but I started from when I was online and everything was fine. Error should be in here: https://pastebin.com/Sdhdq593
    • Update: I stand corrected as I was able to dig up a relevant log from my earlier testing which highlights the overall issue but does not explain how to solve it. See, Diagnostic Logs for pack.mcmeta not found: https://pastebin.com/LXS8Rtna
    • Which mod was this? What are all the mods that were in use? It will help if enough information to replicate the problem is available.
    • I have been attempting to create a supplementary resource pack with Patchouli in order to add back the guidebook for Better End but unfortunately in every prototype I have made pack.mcmeta and my resource pack are not recognized. I have tested both zipped and unzipped and either way curseforge does not recognize my resource pack as existing. For testing I stripped my pack down to just the pack.mcmeta file and two empty folders labelled data and assets and I know the data folder is not the problem as firstly my first attempts just had an assets folder following Patchouli instructions and data came later in my flailing attempts to make anything in my pack work. The mcmeta file is not recognized whether or not I use this:  { "pack": { "pack_format": 15, "description": "A replacement for the BetterEnd Guide Book." } "language": { "en_US": { "name": "English", "region": "United States" } } } ,or this:  { "pack": { "pack_format": 15, "description": "A replacement for the BetterEnd Guide Book." } } I have made sure to only use lowercase and the pack folder is named better-end-guide. Is this some magic nonsense from me doing this manually instead of using an IDE or similar tool? Could it be because my files are by default in UTF-8 even though ANSI gives the same results? Is there a specific community secret tool I am supposed to use for zipping or specific settings? I am pulling my hair in distress. Unfortunately as there are no errors involved I lack logs to offer, if that disqualifies this thread please do not be harsh and instead if you can then please direct me to a forum with different rules and sufficiently respectful but knowledgeable as to be of assistance. Most of my experience with the programming community has been poor and so naturally I find myself wary.
  • Topics

  • Who's Online (See full list)

    • There are no registered users currently online
×
×
  • Create New...

Important Information

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