March 5, 20205 yr Author IGrowable is only used by plant-blocks with multiple grow-states. And not by the flowers.
March 5, 20205 yr Not true. GrassBlock also implements IGrowable, which is where you should be looking.
March 5, 20205 yr Author 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 March 5, 20205 yr by Drachenbauer
March 6, 20205 yr Author 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
March 10, 20205 yr 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.
March 12, 20205 yr Author 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 March 12, 20205 yr by Drachenbauer
March 12, 20205 yr Author 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.