package blusunrize.immersiveengineering.common.items; import blusunrize.immersiveengineering.api.Lib; import blusunrize.immersiveengineering.api.energy.DieselHandler; import blusunrize.immersiveengineering.api.shader.CapabilityShader; import blusunrize.immersiveengineering.api.shader.CapabilityShader.ShaderWrapper; import blusunrize.immersiveengineering.api.shader.CapabilityShader.ShaderWrapper_Item; import blusunrize.immersiveengineering.api.tool.IDrillHead; import blusunrize.immersiveengineering.api.tool.ITool; import blusunrize.immersiveengineering.client.models.IOBJModelCallback; import blusunrize.immersiveengineering.common.gui.IESlot; import blusunrize.immersiveengineering.common.items.IEItemInterfaces.IAdvancedFluidItem; import blusunrize.immersiveengineering.common.util.IEAchievements; import blusunrize.immersiveengineering.common.util.IEItemFluidHandler; import blusunrize.immersiveengineering.common.util.ItemNBTHelper; import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.I18n; 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.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketBlockChange; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.HashMap; import java.util.List; import java.util.Set; public class ItemDrill extends ItemUpgradeableTool implements IAdvancedFluidItem, IOBJModelCallback<ItemStack>, ITool { public static Material[] validMaterials = {Material.ANVIL,Material.CLAY,Material.GLASS,Material.GRASS,Material.GROUND,Material.ICE,Material.IRON,Material.PACKED_ICE,Material.PISTON,Material.ROCK,Material.SAND, Material.SNOW}; public ItemDrill() { super("drill", 1, "DRILL", "diesel"); } @Override public int getInternalSlots(ItemStack stack) { return 5; } @Override public Slot[] getWorkbenchSlots(Container container, ItemStack stack, IInventory invItem) { return new Slot[] { new IESlot.DrillHead(container, invItem,0, 98,22), new IESlot.Upgrades(container, invItem,1, 78,42, "DRILL", stack, true), new IESlot.Upgrades(container, invItem,2, 98,52, "DRILL", stack, true), new IESlot.Upgrades(container, invItem,3, 118,42, "DRILL", stack, true) }; } @Override public boolean canModify(ItemStack stack) { return true; } @Override public void recalculateUpgrades(ItemStack stack) { super.recalculateUpgrades(stack); FluidStack fs = getFluid(stack); if(fs!=null && fs.amount>this.getCapacity(stack,2000)) { fs.amount = this.getCapacity(stack,2000); ItemNBTHelper.setFluidStack(stack, "Fluid",fs); } } @Override public void finishUpgradeRecalculation(ItemStack stack) { FluidStack fs = getFluid(stack); if(fs!=null && fs.amount > getCapacity(stack,2000)) { fs.amount = getCapacity(stack,2000); ItemNBTHelper.setFluidStack(stack, "Fluid", fs); } } @Override public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean adv) { FluidStack fs = getFluid(stack); if(fs!=null) list.add(I18n.format(Lib.DESC_FLAVOUR+"drill.fuel")+" "+fs.amount+"/"+getCapacity(stack,2000)+"mB"); else list.add(I18n.format(Lib.DESC_FLAVOUR+"drill.empty")); if(getHead(stack)==null) list.add(I18n.format(Lib.DESC_FLAVOUR+"drill.noHead")); else { int maxDmg = getMaxHeadDamage(stack); int dmg = maxDmg-getHeadDamage(stack); float quote = dmg/(float)maxDmg; String status = ""+(quote<.1? TextFormatting.RED: quote<.3? TextFormatting.GOLD: quote<.6? TextFormatting.YELLOW: TextFormatting.GREEN); list.add(I18n.format(Lib.DESC_FLAVOUR + "drill.headDamage") + " " + status + dmg + "/" + maxDmg); } } /*RENDER STUFF*/ @Override public boolean isFull3D() { return true; } public static HashMap<String, Integer> animationTimer = new HashMap<String, Integer>(); @Override public boolean onEntitySwing(EntityLivingBase entityLiving, ItemStack stack) { if(canDrillBeUsed(stack, entityLiving)) { if(!animationTimer.containsKey(entityLiving.getName())) animationTimer.put(entityLiving.getName(), 40); else if(animationTimer.get(entityLiving.getName())<20) animationTimer.put(entityLiving.getName(), 20); } return true; } @SideOnly(Side.CLIENT) @Override public TextureAtlasSprite getTextureReplacement(ItemStack stack, String material) { if(material.equals("head") && this.getHead(stack)!=null && this.getHead(stack).getItem() instanceof IDrillHead) { TextureAtlasSprite spr = ((IDrillHead)this.getHead(stack).getItem()).getDrillTexture(stack, this.getHead(stack)); return spr; } return null; } @SideOnly(Side.CLIENT) @Override public boolean shouldRenderGroup(ItemStack stack, String group) { if(group.equals("drill_frame")||group.equals("drill_grip")) return true; NBTTagCompound upgrades = this.getUpgrades(stack); if(group.equals("upgrade_waterproof")) return upgrades.getBoolean("waterproof"); if(group.equals("upgrade_speed")) return upgrades.getInteger("speed")>0; if(this.getHead(stack) != null) { if(group.equals("drill_head")) return true; if(group.equals("upgrade_damage0")) return upgrades.getInteger("damage") > 0; if(group.equals("upgrade_damage1") || group.equals("upgrade_damage2")) return upgrades.getInteger("damage") > 1; if(group.equals("upgrade_damage3") || group.equals("upgrade_damage4")) return upgrades.getInteger("damage") > 2; } return false; } @SideOnly(Side.CLIENT) @Override public Optional<TRSRTransformation> applyTransformations(ItemStack stack, String group, Optional<TRSRTransformation> transform) { if(transform.isPresent()) { NBTTagCompound upgrades = this.getUpgrades(stack); if(group.equals("drill_head") && upgrades.getInteger("damage")<=0) { Matrix4 mat = new Matrix4(transform.get().getMatrix()); mat.translate(-.25f,0,0); return Optional.of(new TRSRTransformation(mat.toMatrix4f())); } if(group.equals("upgrade_damage1")||group.equals("upgrade_damage2")||group.equals("upgrade_damage3")||group.equals("upgrade_damage4")) { Matrix4 mat = new Matrix4(transform.get().getMatrix()); mat.translate(.441f,0,0); return Optional.of(new TRSRTransformation(mat.toMatrix4f())); } } return transform; } @SideOnly(Side.CLIENT) @Override public Matrix4 handlePerspective(ItemStack stack, TransformType cameraTransformType, Matrix4 perspective) { return perspective; } @Override public double getDurabilityForDisplay(ItemStack stack) { return (double)getHeadDamage(stack) / (double)getMaxHeadDamage(stack); } @Override public boolean showDurabilityBar(ItemStack stack) { return getHeadDamage(stack)>0; } @Override public EnumAction getItemUseAction(ItemStack p_77661_1_) { return EnumAction.BOW; } @Override public void removeFromWorkbench(EntityPlayer player, ItemStack stack) { ItemStack[] contents = this.getContainedItems(stack); player.addStat(IEAchievements.craftDrill); if(contents[0]!=null&&contents[1]!=null&&contents[2]!=null&&contents[3]!=null) player.addStat(IEAchievements.upgradeDrill); } /*INVENTORY STUFF*/ public ItemStack getHead(ItemStack drill) { ItemStack head = this.getContainedItems(drill)[0]; return head!=null&&head.getItem() instanceof IDrillHead?head: null; } public void setHead(ItemStack drill, ItemStack head) { ItemStack[] inv = this.getContainedItems(drill); inv[0] = head; this.setContainedItems(drill, inv); } /*TOOL STUFF*/ @Override public boolean isTool(ItemStack item) { return true; } public boolean canDrillBeUsed(ItemStack drill, EntityLivingBase player) { if(drill.getItemDamage()==0 && player.isInsideOfMaterial(Material.WATER) && !getUpgrades(drill).getBoolean("waterproof")) return false; return !(drill.getItemDamage() == 0 && getFluid(drill) == null); } public int getMaxHeadDamage(ItemStack stack) { ItemStack head = getHead(stack); return head!=null?((IDrillHead)head.getItem()).getMaximumHeadDamage(head): 0; } public int getHeadDamage(ItemStack stack) { ItemStack head = getHead(stack); return head!=null?((IDrillHead)head.getItem()).getHeadDamage(head): 0; } public boolean isDrillBroken(ItemStack stack) { return getHeadDamage(stack)>=getMaxHeadDamage(stack) || getFluid(stack)==null || getFluid(stack).amount<1; } // @Override // public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) // { // if(player.isSneaking()) // player.openGui(ImmersiveEngineering.instance, Lib.GUIID_Workbench, world, (int)player.posX,(int)player.posY,(int)player.posZ); // return stack; // } @Override public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase player) { return true; } @Override public boolean onBlockDestroyed(ItemStack stack, World world, IBlockState state, BlockPos pos, EntityLivingBase living) { if((double)state.getBlockHardness(world, pos) != 0.0D) { int dmg = ForgeHooks.isToolEffective(world, pos, stack)?1:3; ItemStack head = getHead(stack); if(head!=null) { if(living instanceof EntityPlayer) { if(((EntityPlayer)living).capabilities.isCreativeMode) return true; ((IDrillHead)head.getItem()).afterBlockbreak(stack, head, (EntityPlayer)living); } ((IDrillHead)head.getItem()).damageHead(head, dmg); this.setHead(stack, head); IFluidHandler handler = FluidUtil.getFluidHandler(stack); handler.drain(1, true); } } return true; } @Override public int getItemEnchantability() { return 0; } @Override public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) { Multimap multimap = super.getAttributeModifiers(slot, stack); if(slot == EntityEquipmentSlot.MAINHAND) { ItemStack head = getHead(stack); if(head != null) multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Tool modifier", ((IDrillHead) head.getItem()).getAttackDamage(head) + getUpgrades(stack).getInteger("damage"), 0)); } return multimap; } @Override public int getHarvestLevel(ItemStack stack, String toolClass) { ItemStack head = getHead(stack); if(head!=null) return ((IDrillHead)head.getItem()).getMiningLevel(head)+ItemNBTHelper.getInt(stack, "harvestLevel"); return 0; } @Override public Set<String> getToolClasses(ItemStack stack) { if(getHead(stack)!=null && !isDrillBroken(stack)) return ImmutableSet.of("pickaxe"); return super.getToolClasses(stack); } public boolean isEffective(Material mat) { for(Material m : validMaterials) if(m == mat) return true; return false; } @Override public boolean canHarvestBlock(IBlockState state, ItemStack stack) { return isEffective(state.getMaterial()) && !isDrillBroken(stack); } @Override public float getStrVsBlock(ItemStack stack, IBlockState state) { ItemStack head = getHead(stack); if(head!=null && !isDrillBroken(stack)) return ((IDrillHead)head.getItem()).getMiningSpeed(head)+ItemNBTHelper.getInt(stack, "speed"); return super.getStrVsBlock(stack, state); } public boolean canBreakExtraBlock(World world, Block block, BlockPos pos, IBlockState state, EntityPlayer player, ItemStack drill, ItemStack head, boolean inWorld) { if(block.canHarvestBlock(world, pos, player) && isEffective(state.getMaterial()) && !isDrillBroken(drill)) { if(inWorld) return !((IDrillHead)head.getItem()).beforeBlockbreak(drill, head, player); else return true; } return false; } @Override public boolean onBlockStartBreak(ItemStack stack, BlockPos iPos, EntityPlayer player) { World world = player.worldObj; if(player.isSneaking() || world.isRemote || !(player instanceof EntityPlayerMP)) return false; RayTraceResult mop = this.rayTrace(world, player, true); ItemStack head = getHead(stack); if(mop==null || head==null || this.isDrillBroken(stack)) return false; // EnumFacing side = mop.sideHit; // int diameter = ((IDrillHead)head.getItem()).getMiningSize(head)+getUpgrades(stack).getInteger("size"); // int depth = ((IDrillHead)head.getItem()).getMiningDepth(head)+getUpgrades(stack).getInteger("depth"); // // BlockPos startPos=iPos; // if(diameter%2==0)//even numbers // { // float hx = (float)mop.hitVec.xCoord-iPos.getX(); // float hy = (float)mop.hitVec.yCoord-iPos.getY(); // float hz = (float)mop.hitVec.zCoord-iPos.getZ(); // if((side.getAxis()==Axis.Y&&hx<.5)||(side.getAxis()==Axis.Z&&hx<.5)) // startPos.add(-diameter/2,0,0); // if(side.getAxis()!=Axis.Y&&hy<.5) // startPos.add(0,-diameter/2,0); // if((side.getAxis()==Axis.Y&&hz<.5)||(side.getAxis()==Axis.X&&hz<.5)) // startPos.add(0,0,-diameter/2); // } // else//odd numbers // { // startPos.add(-(side.getAxis()==Axis.X?0: diameter/2), -(side.getAxis()==Axis.Y?0: diameter/2), -(side.getAxis()==Axis.Z?0: diameter/2)); // } // // for(int dd=0; dd<depth; dd++) // for(int dw=0; dw<diameter; dw++) // for(int dh=0; dh<diameter; dh++) // { // BlockPos pos = startPos.add((side.getAxis()==Axis.X?dd: dw), (side.getAxis()==Axis.Y?dd: dh), (side.getAxis()==Axis.Y?dh: side.getAxis()==Axis.X?dw: dd)); // if(pos.equals(iPos)) // continue; ImmutableList<BlockPos> additional = ((IDrillHead)head.getItem()).getExtraBlocksDug(head, world, player, mop); for(BlockPos pos : additional) { if(!world.isBlockLoaded(pos)) continue; IBlockState state = world.getBlockState(pos); Block block = state.getBlock(); if(block!=null && !block.isAir(state, world, pos) && state.getPlayerRelativeBlockHardness(player, world, pos) != 0) { if(!this.canBreakExtraBlock(world, block, pos, state, player, stack, head, true)) continue; int xpDropEvent = ForgeHooks.onBlockBreakEvent(world, ((EntityPlayerMP)player).interactionManager.getGameType(), (EntityPlayerMP) player, pos); if(xpDropEvent<0) continue; if(player.capabilities.isCreativeMode) { block.onBlockHarvested(world, pos, state, player); if (block.removedByPlayer(state, world, pos, player, false)) block.onBlockDestroyedByPlayer(world, pos, state); } else { block.onBlockHarvested(world, pos, state, player); TileEntity te = world.getTileEntity(pos); //implicitly damages head stack.onBlockDestroyed(world, state, pos, player); if(block.removedByPlayer(state, world, pos, player, true)) { block.onBlockDestroyedByPlayer( world, pos, state); block.harvestBlock(world, player, pos, state, te, stack); block.dropXpOnBlockBreak(world, pos, xpDropEvent); } } world.playEvent(2001, pos, Block.getStateId(state)); ((EntityPlayerMP)player).connection.sendPacket(new SPacketBlockChange(world, pos)); } } return false; } @Override public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { if(slotChanged) return true; if(oldStack.hasCapability(CapabilityShader.SHADER_CAPABILITY,null) && newStack.hasCapability(CapabilityShader.SHADER_CAPABILITY,null)) { ShaderWrapper wrapperOld = oldStack.getCapability(CapabilityShader.SHADER_CAPABILITY,null); ShaderWrapper wrapperNew = newStack.getCapability(CapabilityShader.SHADER_CAPABILITY,null); if(!ItemStack.areItemStacksEqual(wrapperOld.getShaderItem(), wrapperNew.getShaderItem())) return true; } return super.shouldCauseReequipAnimation(oldStack,newStack,slotChanged); } @Override public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt) { return new ICapabilityProvider() { IEItemFluidHandler fluids = new IEItemFluidHandler(stack, 2000); ShaderWrapper_Item shaders = new ShaderWrapper_Item("immersiveengineering:drill", stack); @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { return capability== CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY || capability== CapabilityShader.SHADER_CAPABILITY; } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { if(capability==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) return (T)fluids; if(capability==CapabilityShader.SHADER_CAPABILITY) return (T)shaders; return null; } }; } @Override public int getCapacity(ItemStack container, int baseCapacity) { return baseCapacity+getUpgrades(container).getInteger("capacity"); } @Override public boolean allowFluid(ItemStack container, FluidStack fluid) { return fluid!=null && DieselHandler.isValidDrillFuel(fluid.getFluid()); } }