Posted March 26, 201411 yr Hi guys, Is there any info anywhere on custom crops in MC 1.7.2? I'm having trouble with mines. There's a new IPlantable interface implemented by BlockBush, is there a way to add my plant types to it? Thanks K. http://www.millenaire.org/img/dynamicsig.png[/img]
March 26, 201411 yr Yea, I'm looking for the same thing for my mod. Btw, I love your mod, Ive always used it!
March 27, 201411 yr I think I was successful in creating custom crops with 1.7.2. I did it as follows. I extended BlockCrops with my own version (I usually do this when modding to allow more control where possible, but you should be able to do this with vanilla BlockCrops): https://gist.github.com/anonymous/9797206 Made a blueberry bush block with: https://gist.github.com/anonymous/9796922 I extended ItemSeedFood with my own version (I usually do this when modding to allow more control where possible, but you should be able to do this with vanilla ItemSeedFood): https://gist.github.com/anonymous/9796951 I made the blueberry seed food item with: https://gist.github.com/anonymous/9796968 Then in my main class of the mod I registered everything with: https://gist.github.com/anonymous/9797030 Check out my tutorials here: http://jabelarminecraft.blogspot.com/
March 27, 201411 yr Author Thanks, I'll check it out. You really should add @Override to your methods though, you'll cry if you don't next time MC gets updated This method makes me think I won't be able to keep my current setup of multiple crops per block though: protected Item func_149866_i() { return Items.wheat_seeds; } Ah well, I guess there's no point anymore anyway. http://www.millenaire.org/img/dynamicsig.png[/img]
March 28, 201411 yr You really should add @Override to your methods though, you'll cry if you don't next time MC gets updated Actually, I usually have Eclipse set up to automatically put those in on save, but I guess when I set up Eclipse on this new computer I forgot to set the preferences. So now I've got them in there. Thanks. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
March 28, 201411 yr Author Ok, forget it. I knew it was stupid, just not that stupid. Turns out that in my refactoring I had deleted the registration of the block. Weird that it doesn't throw an error though. http://www.millenaire.org/img/dynamicsig.png[/img]
September 22, 201411 yr I think I was successful in creating custom crops with 1.7.2. I did it as follows. <snip> I tried this code out, and minecraft crashed. Apparently it was from this line? return this.field_149867_a[p_149691_2_]; Which was inside the getIcon method in your custom BlockCrops class. So I suppose it was a problem with getting the textures? How was this line supposed to go? It would be very helpful if you responded. Everyone else's posts/tutorials about crops are extremely outdated. Thanks!
September 22, 201411 yr Everyone else's posts/tutorials about crops are extremely outdated. You might want to look at my tutorial on crops for 1.7.x: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-creating-custom.html Check out my tutorials here: http://jabelarminecraft.blogspot.com/
September 22, 201411 yr Everyone else's posts/tutorials about crops are extremely outdated. You might want to look at my tutorial on crops for 1.7.x: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-creating-custom.html It's the same problem, except with more human readable names. The crash now hapens in this line: return iIcon[parGrowthStage]; Within the getIcon method. What's going on with getIcon? Is nothing ever put in the iIcon array?
September 23, 201411 yr Here is a file that i use, it works great and all you have to do is just extend the file for your new crop and fill in the blanks package your.mod; import java.util.ArrayList; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockBush; import net.minecraft.block.IGrowable; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public abstract class BlockModCrop extends BlockBush implements IGrowable { @SideOnly(Side.CLIENT) private IIcon[] icons; private int amountOfStages; private String cropName; public BlockModCrop(String name, int stages, String crop) { this.setTickRandomly(true); float f = 0.5F; this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.25F, 0.5F + f); this.setCreativeTab((CreativeTabs)null); this.setHardness(0.0F); this.setStepSound(soundTypeGrass); this.disableStats(); GameRegistry.registerBlock(this, name); amountOfStages = stages; cropName = crop; } @Override protected boolean canPlaceBlockOn(Block block) { return block == Blocks.farmland; } @Override public void updateTick(World w, int x, int y, int z, Random r) { super.updateTick(w, x, y, z, r); if(w.getBlockLightValue(x, y + 1, z) >= 9) { int l = w.getBlockMetadata(x, y, z); if(l < amountOfStages) { float f = this.grow(w, x, y, z); if(r.nextInt((int)(25.0F / f) + 1) == 0) { ++l; w.setBlockMetadataWithNotify(x, y, z, l, 2); } } } } public void boneMeal(World w, int x, int y, int z) { int meta = w.getBlockMetadata(x, y, z) + MathHelper.getRandomIntegerInRange(w.rand, 2, 5); if(meta > amountOfStages) meta = amountOfStages; w.setBlockMetadataWithNotify(x, y, z, meta, 2); } private float grow(World w, int x, int y, int z) { float f = 1.0F; Block block = w.getBlock(x, y, z - 1); Block block1 = w.getBlock(x, y, z + 1); Block block2 = w.getBlock(x - 1, y, z); Block block3 = w.getBlock(x + 1, y, z); Block block4 = w.getBlock(x - 1, y, z - 1); Block block5 = w.getBlock(x + 1, y, z - 1); Block block6 = w.getBlock(x + 1, y, z + 1); Block block7 = w.getBlock(x - 1, y, z + 1); boolean flag = block2 == this || block3 == this; boolean flag1 = block == this || block1 == this; boolean flag2 = block4 == this || block5 == this || block6 == this || block7 == this; for(int l = x - 1; l <= x + 1; ++l) { for(int i1 = z - 1; i1 <= z + 1; ++i1) { float f1 = 0.0F; if(w.getBlock(l, y - 1, i1).canSustainPlant(w, l, y - 1, i1, ForgeDirection.UP, this)) { f1 = 1.0F; if (w.getBlock(l, y - 1, i1).isFertile(w, l, y - 1, i1)) f1 = 3.0F; } if(l != x || i1 != z) f1 /= 4.0F; f += f1; } } if(flag2 || flag && flag1) f /= 2.0F; return f; } @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int p_149691_1_, int meta) { if (meta < 0 || meta > amountOfStages) meta = amountOfStages; return this.icons[meta]; } @Override public boolean func_149851_a(World w, int x, int y, int z, boolean b) { return w.getBlockMetadata(x, y, z) != amountOfStages; } @Override public boolean func_149852_a(World w, Random r, int x, int y, int z) { return true; } @Override public void dropBlockAsItemWithChance(World w, int x, int y, int z, int m, float f, int i) { super.dropBlockAsItemWithChance(w, x, y, z, m, f, 0); } @Override public Item getItemDropped(int meta, Random r, int i) { return meta == amountOfStages ? this.getDropItem() : this.getSeeds(); } @Override public int quantityDropped(Random r) { return r.nextInt(2) + 1; } public abstract Item getDropItem(); public abstract Item getSeeds(); @Override @SideOnly(Side.CLIENT) public Item getItem(World w, int x, int y, int z) { return this.getSeeds(); } @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister icon) { this.icons = new IIcon[amountOfStages + 1]; for(int i = 0; i < this.icons.length; ++i) this.icons[i] = icon.registerIcon("MODID:" + cropName + "_" + i); } @Override public void func_149853_b(World w, Random r, int x, int y, int z) { this.boneMeal(w, x, y, z); } @Override public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) { ArrayList<ItemStack> ret = super.getDrops(world, x, y, z, metadata, fortune); if(metadata >= amountOfStages) { for(int i = 0; i < 3 + fortune; i++) { if(world.rand.nextInt(15) <= metadata) ret.add(new ItemStack(this.getSeeds(), 1, 0)); } } return ret; } } After you read the code, you should know how to use it. Former developer for DivineRPG, Pixelmon and now the maker of Essence of the Gods
September 23, 201411 yr Here is a file that i use, it works great and all you have to do is just extend the file for your new crop and fill in the blanks package your.mod; import java.util.ArrayList; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockBush; import net.minecraft.block.IGrowable; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public abstract class BlockModCrop extends BlockBush implements IGrowable { @SideOnly(Side.CLIENT) private IIcon[] icons; private int amountOfStages; private String cropName; public BlockModCrop(String name, int stages, String crop) { this.setTickRandomly(true); float f = 0.5F; this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.25F, 0.5F + f); this.setCreativeTab((CreativeTabs)null); this.setHardness(0.0F); this.setStepSound(soundTypeGrass); this.disableStats(); GameRegistry.registerBlock(this, name); amountOfStages = stages; cropName = crop; } @Override protected boolean canPlaceBlockOn(Block block) { return block == Blocks.farmland; } @Override public void updateTick(World w, int x, int y, int z, Random r) { super.updateTick(w, x, y, z, r); if(w.getBlockLightValue(x, y + 1, z) >= 9) { int l = w.getBlockMetadata(x, y, z); if(l < amountOfStages) { float f = this.grow(w, x, y, z); if(r.nextInt((int)(25.0F / f) + 1) == 0) { ++l; w.setBlockMetadataWithNotify(x, y, z, l, 2); } } } } public void boneMeal(World w, int x, int y, int z) { int meta = w.getBlockMetadata(x, y, z) + MathHelper.getRandomIntegerInRange(w.rand, 2, 5); if(meta > amountOfStages) meta = amountOfStages; w.setBlockMetadataWithNotify(x, y, z, meta, 2); } private float grow(World w, int x, int y, int z) { float f = 1.0F; Block block = w.getBlock(x, y, z - 1); Block block1 = w.getBlock(x, y, z + 1); Block block2 = w.getBlock(x - 1, y, z); Block block3 = w.getBlock(x + 1, y, z); Block block4 = w.getBlock(x - 1, y, z - 1); Block block5 = w.getBlock(x + 1, y, z - 1); Block block6 = w.getBlock(x + 1, y, z + 1); Block block7 = w.getBlock(x - 1, y, z + 1); boolean flag = block2 == this || block3 == this; boolean flag1 = block == this || block1 == this; boolean flag2 = block4 == this || block5 == this || block6 == this || block7 == this; for(int l = x - 1; l <= x + 1; ++l) { for(int i1 = z - 1; i1 <= z + 1; ++i1) { float f1 = 0.0F; if(w.getBlock(l, y - 1, i1).canSustainPlant(w, l, y - 1, i1, ForgeDirection.UP, this)) { f1 = 1.0F; if (w.getBlock(l, y - 1, i1).isFertile(w, l, y - 1, i1)) f1 = 3.0F; } if(l != x || i1 != z) f1 /= 4.0F; f += f1; } } if(flag2 || flag && flag1) f /= 2.0F; return f; } @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int p_149691_1_, int meta) { if (meta < 0 || meta > amountOfStages) meta = amountOfStages; return this.icons[meta]; } @Override public boolean func_149851_a(World w, int x, int y, int z, boolean b) { return w.getBlockMetadata(x, y, z) != amountOfStages; } @Override public boolean func_149852_a(World w, Random r, int x, int y, int z) { return true; } @Override public void dropBlockAsItemWithChance(World w, int x, int y, int z, int m, float f, int i) { super.dropBlockAsItemWithChance(w, x, y, z, m, f, 0); } @Override public Item getItemDropped(int meta, Random r, int i) { return meta == amountOfStages ? this.getDropItem() : this.getSeeds(); } @Override public int quantityDropped(Random r) { return r.nextInt(2) + 1; } public abstract Item getDropItem(); public abstract Item getSeeds(); @Override @SideOnly(Side.CLIENT) public Item getItem(World w, int x, int y, int z) { return this.getSeeds(); } @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister icon) { this.icons = new IIcon[amountOfStages + 1]; for(int i = 0; i < this.icons.length; ++i) this.icons[i] = icon.registerIcon("MODID:" + cropName + "_" + i); } @Override public void func_149853_b(World w, Random r, int x, int y, int z) { this.boneMeal(w, x, y, z); } @Override public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) { ArrayList<ItemStack> ret = super.getDrops(world, x, y, z, metadata, fortune); if(metadata >= amountOfStages) { for(int i = 0; i < 3 + fortune; i++) { if(world.rand.nextInt(15) <= metadata) ret.add(new ItemStack(this.getSeeds(), 1, 0)); } } return ret; } } After you read the code, you should know how to use it. This is pretty good. I just have to add and mess with getRenderType and it should be working fine. Also, I'm not sure why you felt the need to register the block within the custom crop class. Don't people usually do that in the main? Anyway, a bit unconventional, but it works. So how do I add the texture? EDIT: Oh, never mind. I saw "MODID:" in registerBlockIcons and didn't notice the quotes, so I assumed that was a variable. So I just replaced that part with my mod id and it works fine. Thanks!
September 23, 201411 yr You can register it either way, but i like to do it inside of the blocks/item class because it saves so much code haha Former developer for DivineRPG, Pixelmon and now the maker of Essence of the Gods
September 23, 201411 yr You can register it either way, but i like to do it inside of the blocks/item class because it saves so much code haha Oh, I know you CAN, but I've never seen anyone do that before. I figured it was against convention or something. Anyway, thanks for the help!
September 23, 201411 yr You can register it either way, but i like to do it inside of the blocks/item class because it saves so much code haha Oh, I know you CAN, but I've never seen anyone do that before. I figured it was against convention or something. Anyway, thanks for the help! I think the issue with registering your block (or item or entity, etc) in their own constructor is that you potentially lose control of the order of registration, or at least you have to be more conscious of how the instantiation order will affect registration order. Sometimes you'll need to control the order. For example with ItemSeeds it is important to have the related blocks registered first. You can control it with instantiation, but many people might be tempted to still instantiate in the field declaration area of the main class. Anyway, just something to keep in mind if you go the route of registering classes within their own constructors. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
September 23, 201411 yr Please see this article on why it is bad to pass 'this' outside the constructor. You should not call registry or any method that uses 'this' when constructing. -S- (if I helped, please click Thank and applaud) http://6upnqa.dm2301.livefilestore.com/y2mtf-vG7Tqq1TiiVpIm53KWj7294NDPoHfSHHb4PzZiMAUfRCfK0UY0MwOu7Q3zTBNVTKqWjr2-xgBfFRpQT5p-QivtvknPpoABMNUw9br9WuZcBFkjePhnAbW500gVm-P/sequiturian.png[/img]
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.