package mekanism.common.item; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.collect.Multimap; import mekanism.api.Coord4D; import mekanism.api.EnumColor; import mekanism.api.MekanismConfig.general; import mekanism.api.util.ListUtils; import mekanism.common.util.ItemDataUtils; import mekanism.common.util.LangUtils; import mekanism.common.util.MekanismUtils; import net.minecraft.block.Block; import net.minecraft.block.BlockDirt; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.DamageSource; 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.util.text.TextComponentString; import net.minecraft.world.World; public class ItemAtomicDisassembler extends ItemEnergized { public double HOE_USAGE = 10 * general.DISASSEMBLER_USAGE; public ItemAtomicDisassembler() { super(1000000); } @Override public boolean canHarvestBlock(IBlockState state, ItemStack stack) { return state.getBlock() != Blocks.BEDROCK; } @Override public void addInformation(ItemStack itemstack, EntityPlayer entityplayer, List<String> list, boolean flag) { super.addInformation(itemstack, entityplayer, list, flag); list.add(LangUtils.localize("tooltip.mode") + ": " + EnumColor.INDIGO + getModeName(itemstack)); list.add(LangUtils.localize("tooltip.efficiency") + ": " + EnumColor.INDIGO + getEfficiency(itemstack)); } @Override public boolean hitEntity(ItemStack itemstack, EntityLivingBase target, EntityLivingBase attacker) { if(getEnergy(itemstack) > 0) { if(attacker instanceof EntityPlayer) { target.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) attacker), 20); } else { target.attackEntityFrom(DamageSource.causeMobDamage(attacker), 20); } setEnergy(itemstack, getEnergy(itemstack) - 2000); } else { if(attacker instanceof EntityPlayer) { target.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer)attacker), 4); } else { target.attackEntityFrom(DamageSource.causeMobDamage(attacker), 4); } } return false; } @Override public float getStrVsBlock(ItemStack itemstack, IBlockState state) { return getEnergy(itemstack) != 0 ? getEfficiency(itemstack) : 1F; } @Override public boolean onBlockDestroyed(ItemStack itemstack, World world, IBlockState state, BlockPos pos, EntityLivingBase entityliving) { if(state.getBlockHardness(world, pos) != 0.0D) { setEnergy(itemstack, getEnergy(itemstack) - (general.DISASSEMBLER_USAGE*getEfficiency(itemstack))); } else { setEnergy(itemstack, getEnergy(itemstack) - (general.DISASSEMBLER_USAGE*(getEfficiency(itemstack))/2)); } return true; } @Override public boolean onBlockStartBreak(ItemStack itemstack, BlockPos pos, EntityPlayer player) { super.onBlockStartBreak(itemstack, pos, player); if(!player.worldObj.isRemote) { IBlockState state = player.worldObj.getBlockState(pos); Block block = state.getBlock(); int meta = block.getMetaFromState(state); if(block == Blocks.LIT_REDSTONE_ORE) { block = Blocks.REDSTONE_ORE; } ItemStack stack = new ItemStack(block, 1, meta); Coord4D orig = new Coord4D(pos, player.worldObj); List<String> names = MekanismUtils.getOreDictName(stack); boolean isOre = false; for(String s : names) { if(s.startsWith("ore") || s.equals("logWood")) { isOre = true; } } if(getMode(itemstack) == 3 && isOre && !player.capabilities.isCreativeMode) { Set<Coord4D> found = new Finder(player.worldObj, stack, new Coord4D(pos, player.worldObj)).calc(); for(Coord4D coord : found) { if(coord.equals(orig) || getEnergy(itemstack) < (general.DISASSEMBLER_USAGE*getEfficiency(itemstack))) { continue; } Block block2 = coord.getBlock(player.worldObj); block2.onBlockDestroyedByPlayer(player.worldObj, coord.getPos(), state); player.worldObj.playEvent(null, 2001, coord.getPos(), Block.getStateId(state)); player.worldObj.setBlockToAir(coord.getPos()); block2.breakBlock(player.worldObj, coord.getPos(), state); block2.dropBlockAsItem(player.worldObj, coord.getPos(), state, 0); setEnergy(itemstack, getEnergy(itemstack) - (general.DISASSEMBLER_USAGE*getEfficiency(itemstack))); } } } return false; } @Override public boolean isFull3D() { return true; } @Override public ActionResult<ItemStack> onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer, EnumHand hand) { if(!world.isRemote && entityplayer.isSneaking()) { toggleMode(itemstack); entityplayer.addChatMessage(new TextComponentString(EnumColor.DARK_BLUE + "[Mekanism] " + EnumColor.GREY + LangUtils.localize("tooltip.modeToggle") + " " + EnumColor.INDIGO + getModeName(itemstack) + EnumColor.AQUA + " (" + getEfficiency(itemstack) + ")")); } return new ActionResult(EnumActionResult.SUCCESS, itemstack); } @Override public EnumActionResult onItemUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) { if(!player.isSneaking()) { if(useHoe(stack, player, world, pos, side) == EnumActionResult.FAIL) { if(world.getBlockState(pos).getBlock() != Blocks.FARMLAND) { return EnumActionResult.FAIL; } } switch(getEfficiency(stack)) { case 20: for(int x1 = -1; x1 <= +1; x1++) { for(int z1 = -1; z1 <= +1; z1++) { useHoe(stack, player, world, pos.add(x1, 0, z1), side); } } break; case 128: for(int x1 = -2; x1 <= +2; x1++) { for(int z1 = -2; z1 <= +2; z1++) { useHoe(stack, player, world, pos.add(x1, 0, z1), side); } } break; } return EnumActionResult.SUCCESS; } return EnumActionResult.PASS; } @SuppressWarnings("incomplete-switch") private EnumActionResult useHoe(ItemStack stack, EntityPlayer playerIn, World worldIn, BlockPos pos, EnumFacing facing) { if(!playerIn.canPlayerEdit(pos.offset(facing), facing, stack)) { return EnumActionResult.FAIL; } else { int hook = net.minecraftforge.event.ForgeEventFactory.onHoeUse(stack, playerIn, worldIn, pos); if(hook != 0) return hook > 0 ? EnumActionResult.SUCCESS : EnumActionResult.FAIL; IBlockState iblockstate = worldIn.getBlockState(pos); Block block = iblockstate.getBlock(); if(facing != EnumFacing.DOWN && worldIn.isAirBlock(pos.up())) { if(block == Blocks.GRASS || block == Blocks.GRASS_PATH) { setBlock(stack, playerIn, worldIn, pos, Blocks.FARMLAND.getDefaultState()); return EnumActionResult.SUCCESS; } if(block == Blocks.DIRT) { switch((BlockDirt.DirtType)iblockstate.getValue(BlockDirt.VARIANT)) { case DIRT: setBlock(stack, playerIn, worldIn, pos, Blocks.FARMLAND.getDefaultState()); return EnumActionResult.SUCCESS; case COARSE_DIRT: setBlock(stack, playerIn, worldIn, pos, Blocks.DIRT.getDefaultState().withProperty(BlockDirt.VARIANT, BlockDirt.DirtType.DIRT)); return EnumActionResult.SUCCESS; } } } return EnumActionResult.PASS; } } protected void setBlock(ItemStack stack, EntityPlayer player, World worldIn, BlockPos pos, IBlockState state) { worldIn.playSound(player, pos, SoundEvents.ITEM_HOE_TILL, SoundCategory.BLOCKS, 1.0F, 1.0F); if(!worldIn.isRemote) { worldIn.setBlockState(pos, state, 11); stack.damageItem(1, player); } } public int getEfficiency(ItemStack itemStack) { switch(getMode(itemStack)) { case 0: return 20; case 1: return 8; case 2: return 128; case 3: return 20; case 4: return 0; } return 0; } public int getMode(ItemStack itemStack) { return ItemDataUtils.getInt(itemStack, "mode"); } public String getModeName(ItemStack itemStack) { int mode = getMode(itemStack); switch(mode) { case 0: return LangUtils.localize("tooltip.disassembler.normal"); case 1: return LangUtils.localize("tooltip.disassembler.slow"); case 2: return LangUtils.localize("tooltip.disassembler.fast"); case 3: return LangUtils.localize("tooltip.disassembler.vein"); case 4: return LangUtils.localize("tooltip.disassembler.off"); } return null; } public void toggleMode(ItemStack itemStack) { ItemDataUtils.setInt(itemStack, "mode", getMode(itemStack) < 4 ? getMode(itemStack)+1 : 0); } @Override public boolean canSend(ItemStack itemStack) { return false; } @Override public Multimap<String, AttributeModifier> getItemAttributeModifiers(EntityEquipmentSlot equipmentSlot) { Multimap<String, AttributeModifier> multimap = super.getItemAttributeModifiers(equipmentSlot); if(equipmentSlot == EntityEquipmentSlot.MAINHAND) { multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", -2.4000000953674316D, 0)); } return multimap; } public static class Finder { public World world; public ItemStack stack; public Coord4D location; public Set<Coord4D> found = new HashSet<Coord4D>(); public static Map<Block, List<Block>> ignoreBlocks = new HashMap<Block, List<Block>>(); public Finder(World w, ItemStack s, Coord4D loc) { world = w; stack = s; location = loc; } public void loop(Coord4D pointer) { if(found.contains(pointer) || found.size() > 128) { return; } found.add(pointer); for(EnumFacing side : EnumFacing.VALUES) { Coord4D coord = pointer.offset(side); if(coord.exists(world) && checkID(coord.getBlock(world)) && (coord.getBlockMeta(world) == stack.getItemDamage() || (MekanismUtils.getOreDictName(stack).contains("logWood") && coord.getBlockMeta(world) % 4 == stack.getItemDamage() % 4))) { loop(coord); } } } public Set<Coord4D> calc() { loop(location); return found; } public boolean checkID(Block b) { Block origBlock = location.getBlock(world); return (ignoreBlocks.get(origBlock) == null && b == origBlock) || (ignoreBlocks.get(origBlock) != null && ignoreBlocks.get(origBlock).contains(b)); } static { ignoreBlocks.put(Blocks.REDSTONE_ORE, ListUtils.asList(Blocks.REDSTONE_ORE, Blocks.LIT_REDSTONE_ORE)); ignoreBlocks.put(Blocks.LIT_REDSTONE_ORE, ListUtils.asList(Blocks.REDSTONE_ORE, Blocks.LIT_REDSTONE_ORE)); } } }