Posted July 16, 20169 yr Hello, I've been making a new item that I'm planning on making to delete log blocks, and replace it with at least 6 plank blocks of that kind of wood. So far, it's got the shovel code (i.e. turn grass into paths) as a placeholder right click event. What could I use to make this item do what I want? Thanks if you can help. If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr #onItemUse gives you the block position / face clicked - check if it's a log, set it to air if it is and drop an ItemStack containing 6 planks. Might be easier to use the crafting recipes to fetch the correct plank for the log given and drop that. http://i.imgur.com/NdrFdld.png[/img]
July 16, 20169 yr Author Ok, how would I drop the item at the block's posistion? I'm not sure which call would spawn an item entity. If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr This code will fix it: worldIn.destroyBlock(new BlockPos(x,y, z), true); true makes it drop items. http://i.imgur.com/J4rrGt6.png[/img] [Creator of mcrafterzz mod]
July 16, 20169 yr Author I added that line into the code, but now it seems to not destroy the block in the world. Here's my code: package com.t10a.minedran.item.tools; import com.t10a.minedran.reference.Reference; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class ItemHandsaw extends Item { private final Item.ToolMaterial material; public ItemHandsaw(ToolMaterial material) { this.material = material; this.setMaxStackSize(1); this.setMaxDamage(material.getMaxUses()); this.setCreativeTab(CreativeTabs.TOOLS); this.setUnlocalizedName(Reference.ItemBase.HANDSAW.getUnlocalizedName() + "_" + getToolMaterialName().toLowerCase()); this.setRegistryName(Reference.ItemBase.HANDSAW.getRegistryName() + "_" + getToolMaterialName().toLowerCase()); } public EnumActionResult onItemUse(ItemStack stack, EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float x, float y, float z) { if (!playerIn.canPlayerEdit(pos.offset(facing), facing, stack)) { return EnumActionResult.FAIL; } else { IBlockState iblockstate = worldIn.getBlockState(pos); Block block = iblockstate.getBlock(); if (facing != EnumFacing.DOWN && worldIn.getBlockState(pos.up()).getMaterial() == Material.AIR && block == Blocks.LOG) { worldIn.destroyBlock(new BlockPos(x,y,z), true); worldIn.playSound(playerIn, pos, SoundEvents.ITEM_SHOVEL_FLATTEN, SoundCategory.BLOCKS, 1.0F, 1.0F); if (!worldIn.isRemote) { stack.damageItem(1, playerIn); } return EnumActionResult.SUCCESS; } else { return EnumActionResult.PASS; } } } public String getToolMaterialName() { return this.material.toString(); } public int getItemEnchantability() { return this.material.getEnchantability(); } public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) { ItemStack mat = this.material.getRepairItemStack(); if (mat != null && net.minecraftforge.oredict.OreDictionary.itemMatches(mat, repair, false)) return true; return super.getIsRepairable(toRepair, repair); } } If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr The three float arguments of Item#onItemUse are where the player clicked on the block. The block's position in the world is given to you as the BlockPos argument. Always annotate override methods with @Override so you get a compilation error if they don't actually override a super method. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
July 16, 20169 yr Author Okay, it works and it drops the log block. How would I check for the type of log, and drop the corresponding plank blocks in a specific amount? If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr Use World#getBlockState to get the IBlockState at the specified position. Use IBlockState#getBlock to get the Block represented by the IBlockState . If you only want to handle vanilla logs, check if the Block is Blocks.LOG or Blocks.LOG2 . If it is, use IBlockState#getValue to get the value of the BlockOldLog.VARIANT property (if it's Blocks.LOG ) or the BlockNewLog.VARIANT property (if it's Blocks.LOG2 ). This will give you a BlockPlanks.EnumType value. You can then create an ItemStack of Blocks.PLANKS , using the value returned by BlockPlanks.EnumType#getMetadata as the metadata. To drop this in the world, use Block.spawnAsEntity . Handling modded logs will be a bit trickier because there's no easy and reliable way to know what the corresponding planks are. You can use Block#isWood to check if a block is a log. To get the corresponding planks, you can either: Assume that a single log in the crafting grid will result in planks (which may or may not be the case): Create an InventoryCrafting with a dummy Container , put an ItemStack of the logs in it and use CraftingManager#findMatchingRecipe to get the resulting planks ItemStack . Pros: Has the potential to work for any mod without having to explicitly add support. Cons: Not guaranteed to work for all mods. [*]Create a class to hold the log to plank conversion recipes (similar to FurnaceRecipes ), register a recipe for each vanilla log and then use this in ItemHandsaw . You can then add recipes for other mods' logs as needed. Pros: Guaranteed to work for any mod you've added support for. Cons: Only works for mods you've explicitly added support for. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
July 16, 20169 yr Author Ok, I'm interested in creating a log to plank recipe class. How would I get started with that? If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr I think the best way to implement this is to have your recipe class store a Map<Block, Function<IBlockState, ItemStack>> . You can then have a method that takes an IBlockState , looks up the Function in the Map using the Block , calls the Function with the IBlockState and returns the resulting ItemStack . Return null if there's no Function for the specified Block . You can then call this method in ItemHandsaw#onItemUse . If it returns a non- null value, set the block to air and drop the ItemStack in the world. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
July 16, 20169 yr Author Okay, I'm starting to make the class. After trying to emulate the furnace recipe class, I've gotten this so far (I know, it won't work. This is as far as I've gone before I start getting lost in what to change to make it work) package com.t10a.minedran.item.crafting; import net.minecraft.item.ItemStack; import com.google.common.collect.Maps; import java.util.Map; import java.util.Map.Entry; import javax.annotation.Nullable; import com.google.common.base.Function; import net.minecraft.block.Block; import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; public class HandsawRecipes { private Map<Block, Function<IBlockState, ItemStack>> handsawList = Maps.<Block, Function<IBlockState, ItemStack>>newHashMap(); private HandsawRecipes(Block input, IBlockState iblockstate, Function<IBlockState, ItemStack> planks) { this.addHandsawRecipe(input, iblockstate, planks); } public void addHandsawRecipe(Block input, IBlockState iblockstate, Function<IBlockState, ItemStack> planks) { if (getSmeltingResult(input) != null) { net.minecraftforge.fml.common.FMLLog.info("Ignored handsaw recipe with conflicting input: " + input + " = " + planks); return; } this.handsawList.put(input, planks); } @Nullable public ItemStack getSmeltingResult(Block input) { for (Entry<Block, Function<IBlockState, ItemStack>> entry : this.handsawList.entrySet()) { if (this.compareItemStacks(input, (Block)entry.getKey())) { return (ItemStack)entry.getValue(); } } return null; } private boolean compareItemStacks(Block input, Block output) { return output.getBlockState() == input.getBlockState(); } public Map<Block, Function<IBlockState, ItemStack>> getSmeltingList() { return this.handsawList; } } If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr The only methods you need in HandsawRecipes are the following: void addHandsawRecipe(Block, Function<IBlockState, ItemStack>) Get the Function for the Block from the Map . If it exists, log or throw an error. If it doesn't, add the Function argument to the Map . [*] @Nullable ItemStack geResult(IBlockState) Get the IBlockState 's Block , then get the Function for that Block from the Map . If there's no Function , return null . If there is a Function , call Function#apply with the IBlockState and return the resulting ItemStack . If you're going to use a singleton instance like FurnaceRecipes does, you'll also need an instance field and a static method to get the instance. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
July 16, 20169 yr Author Okay, I cleaned up the code, and I'm now getting a syntax error of 'Syntax error, insert "... VariableDeclaratorId" to complete FormalParameter' with Block & IBlockState, as well as Eclipse wanting to take out a bunch of brackets. Here's what I've cleaned up and tweaked so far: package com.t10a.minedran.item.crafting; import java.util.Map; import javax.annotation.Nullable; import com.google.common.base.Function; import com.google.common.collect.Maps; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.FurnaceRecipes; public class HandsawRecipes { private static final HandsawRecipes HANDSAW_RECIPES = new HandsawRecipes(); private Map<Block, Function<IBlockState, ItemStack>> handsawList = Maps.<Block, Function<IBlockState, ItemStack>>newHashMap(); public static HandsawRecipes instance() { return HANDSAW_RECIPES; } public HandsawRecipes() { } public void addHandsawRecipe(Block, Function<IBlockState, ItemStack>) { } @Nullable public ItemStack geResult(IBlockState) { for (Entry<ItemStack, ItemStack> entry : this.handsawList.entrySet()) { if (this.compareItemStacks(stack, (ItemStack)entry.getKey())) { return (ItemStack)entry.getValue(); } } return null; } } If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
July 16, 20169 yr The method signatures I posted aren't valid Java themselves, they're using an abbreviated notation without the parameter names. You weren't meant to blindly copy-paste them. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
July 17, 20169 yr Author Sorry about that... I'm not familiar with Functions<> and creating custom recipe handlers. But I'm learning along the way. If I'm asking a whole bunch of questions, please don't get angry. I'm trying to learn.
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.