gt:         statY = entityTrackInfo.getBaseY();
context: package pneumaticCraft.client.render.pneumaticArmor;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  
  import net.minecraft.client.Minecraft;
  import net.minecraft.client.gui.ScaledResolution;
  import net.minecraft.entity.Entity;
  import net.minecraft.entity.EntityLivingBase;
  import net.minecraft.entity.monster.EntityMob;
  import net.minecraft.entity.player.EntityPlayer;
  import net.minecraft.item.ItemStack;
  import net.minecraft.util.AxisAlignedBB;
  import net.minecraft.util.EnumChatFormatting;
  import net.minecraft.util.Vec3;
  import net.minecraftforge.client.event.MouseEvent;
  import net.minecraftforge.common.MinecraftForge;
  import net.minecraftforge.common.config.Configuration;
  import pneumaticCraft.api.client.pneumaticHelmet.EntityTrackEvent;
  import pneumaticCraft.api.client.pneumaticHelmet.IOptionPage;
  import pneumaticCraft.api.client.pneumaticHelmet.IUpgradeRenderHandler;
  import pneumaticCraft.client.gui.pneumaticHelmet.GuiEntityTrackOptions;
  import pneumaticCraft.client.gui.widget.GuiAnimatedStat;
  import pneumaticCraft.common.CommonHUDHandler;
  import pneumaticCraft.common.NBTUtil;
  import pneumaticCraft.common.config.Config;
  import pneumaticCraft.common.item.ItemMachineUpgrade;
  import pneumaticCraft.common.item.Itemss;
  import pneumaticCraft.common.util.PneumaticCraftUtils;
  import pneumaticCraft.lib.PneumaticValues;
  import cpw.mods.fml.relauncher.Side;
  import cpw.mods.fml.relauncher.SideOnly;
  
  public class EntityTrackUpgradeHandler implements IUpgradeRenderHandler{
  
      private final List<RenderTarget> targets = new ArrayList<RenderTarget>();
      private final Map<Entity, Integer> targetingEntities = new HashMap<Entity, Integer>();
      private boolean shouldStopSpamOnEntityTracking = false;
      private static final int ENTITY_TRACK_THRESHOLD = 7;
      private static final float ENTITY_TRACKING_RANGE = 16F;
      public boolean gaveNotAbleToTrackEntityWarning;
  
      @SideOnly(Side.CLIENT)
      private GuiAnimatedStat entityTrackInfo;
      private int statX;
      private int statY;
      private boolean statLeftSided;
      public static String UPGRADE_NAME = "entityTracker";
  
      @Override
      @SideOnly(Side.CLIENT)
      public String getUpgradeName(){
          return UPGRADE_NAME;
      }
  
      @Override
      @SideOnly(Side.CLIENT)
      public void update(EntityPlayer player, int rangeUpgrades){
          ItemStack helmetStack = player.getCurrentArmor(3);
          String entityFilter = "";
          if(helmetStack != null) entityFilter = NBTUtil.getString(helmetStack, "entityFilter");
          double entityTrackRange = ENTITY_TRACKING_RANGE + rangeUpgrades * PneumaticValues.RANGE_UPGRADE_HELMET_RANGE_INCREASE;
          AxisAlignedBB bbBox = getAABBFromRange(player, rangeUpgrades);
          List<Entity> mobs = player.worldObj.getEntitiesWithinAABB(EntityLivingBase.class, bbBox);
          if(mobs.contains(player)) mobs.remove(player);
          for(int i = 0; i < mobs.size(); i++) {
              if(player.getDistanceToEntity(mobs.get(i)) > entityTrackRange || !PneumaticCraftUtils.isEntityValidForFilter(entityFilter, mobs.get(i)) || MinecraftForge.EVENT_BUS.post(new EntityTrackEvent(mobs.get(i)))) continue;
              boolean inList = false;
              for(int j = 0; j < targets.size(); j++) {
                  if(targets.get(j).entity == mobs.get(i)) {
                      inList = true;
                      targets.get(j).ticksExisted = Math.abs(targets.get(j).ticksExisted);// cancel
                                                                                          // lost
                                                                                          // targets
                      break;
                  }
              }
              if(!inList) {
                  //player.worldObj.playSoundAtEntity(player, Sounds.CANNON_SOUND, 1.0F, 1.0F);
                  targets.add(new RenderTarget(mobs.get(i)));
                  if(mobs.get(i) instanceof EntityMob && !isEntityWithinPlayerFOV(player, mobs.get(i))) {
                      //       HUDHandler.instance().addMessage(new ArmorMessage("A mob is sneaking up on you!", new ArrayList<String>(), 60, 0x70FF0000));
                  }
              }
          }
          for(int j = 0; j < targets.size(); j++) {
              RenderTarget target = targets.get(j);
              if(target.entity.isDead || player.getDistanceToEntity(target.entity) > entityTrackRange + 5 || !PneumaticCraftUtils.isEntityValidForFilter(entityFilter, target.entity)) {
                  if(target.ticksExisted > 0) {
                      target.ticksExisted = -60;
                  } else if(target.ticksExisted == -1) {
                      targets.remove(target);
                      j--;
                  }
              }
          }
          if(targets.size() > ENTITY_TRACK_THRESHOLD) {
              if(!shouldStopSpamOnEntityTracking) {
                  shouldStopSpamOnEntityTracking = true;
                  HUDHandler.instance().addMessage(new ArmorMessage("Stopped spam on Entity Tracker", new ArrayList<String>(), 60, 0x7700AA00));
              }
          } else {
              shouldStopSpamOnEntityTracking = false;
          }
          List<String> text = new ArrayList<String>();
          for(RenderTarget target : targets) {
              boolean wasNegative = target.ticksExisted < 0;
              target.ticksExisted += CommonHUDHandler.getHandlerForPlayer(player).getSpeedFromUpgrades();
              if(target.ticksExisted >= 0 && wasNegative) target.ticksExisted = -1;
              target.update();
              if(target.isLookingAtTarget) {
                  if(target.isInitialized()) {
                      text.add(EnumChatFormatting.GRAY + target.entity.getCommandSenderName());
                      text.addAll(target.getEntityText());
                  } else {
                      text.add(EnumChatFormatting.GRAY + "Acquiring target...");
                  }
              }
          }
          if(text.size() == 0) {
              text.add("Filter mode: " + (entityFilter.equals("") ? "None" : entityFilter));
          }
          entityTrackInfo.setText(text);
  
          //Remove entities that don't need to be tracked anymore.
          Iterator<Entry<Entity, Integer>> iterator = targetingEntities.entrySet().iterator();
          while(iterator.hasNext()) {
              Entry<Entity, Integer> entry = iterator.next();
              Entity entity = entry.getKey();
              if(entry.getValue() >= 0) entry.setValue(entry.getValue() + 1);
              if(entity.isDead || !player.worldObj.getLoadedEntityList().contains(entity) || entry.getValue() > 50) iterator.remove();
          }
      }
  
      public void warnIfNecessary(Entity entity){
          if(!targetingEntities.containsKey(entity)) {
              HUDHandler.instance().addMessage(new ArmorMessage("A mob is targeting you!", new ArrayList<String>(), 60, 0x70FF0000));
          }
          targetingEntities.put(entity, -1);
      }
  
      public void removeTargetingEntity(Entity entity){
          if(targetingEntities.containsKey(entity)) {
              targetingEntities.put(entity, 0);
          }
      }
  
      public static AxisAlignedBB getAABBFromRange(EntityPlayer player, int rangeUpgrades){
          double entityTrackRange = ENTITY_TRACKING_RANGE + Math.min(10, rangeUpgrades) * PneumaticValues.RANGE_UPGRADE_HELMET_RANGE_INCREASE;
  
          return AxisAlignedBB.getBoundingBox(player.posX - entityTrackRange, player.posY - entityTrackRange, player.posZ - entityTrackRange, player.posX + entityTrackRange, player.posY + entityTrackRange, player.posZ + entityTrackRange);
      }
  
      private boolean isEntityWithinPlayerFOV(EntityPlayer player, Entity entity){
          // code used from the Enderman player looking code.
          Vec3 vec3 = player.getLook(1.0F).normalize();
          Vec3 vec31 = Vec3.createVectorHelper(entity.posX - player.posX, entity.boundingBox.minY + entity.height / 2.0F - (player.posY + player.getEyeHeight()), entity.posZ - player.posZ);
          double d0 = vec31.lengthVector();
          vec31 = vec31.normalize();
          double d1 = vec3.dotProduct(vec31);
          return d1 > 1.0D - 2.5D / d0;
          // return d1 > 1.0D - 0.025D / d0;
      }
  
      @Override
      @SideOnly(Side.CLIENT)
      public void render3D(float partialTicks){
          for(RenderTarget target : targets) {
              target.render(partialTicks, shouldStopSpamOnEntityTracking);
          }
      }
  
      @Override
      @SideOnly(Side.CLIENT)
      public void render2D(float partialTicks, boolean upgradeEnabled){}
  
      @Override
      public boolean isEnabled(ItemStack[] upgradeStacks){
          for(ItemStack stack : upgradeStacks) {
              if(stack != null && stack.getItem() == Itemss.machineUpgrade && stack.getItemDamage() == ItemMachineUpgrade.UPGRADE_ENTITY_TRACKER) return true;
          }
          return false;
      }
  
      @Override
      @SideOnly(Side.CLIENT)
      public void reset(){
          targets.clear();
      }
  
      @Override
      public float getEnergyUsage(int rangeUpgrades, EntityPlayer player){
          return PneumaticValues.USAGE_ENTITY_TRACKER * (1 + (float)Math.min(10, rangeUpgrades) * PneumaticValues.RANGE_UPGRADE_HELMET_RANGE_INCREASE / ENTITY_TRACKING_RANGE) * CommonHUDHandler.getHandlerForPlayer(player).getSpeedFromUpgrades();
      }
  
      @Override
      @SideOnly(Side.CLIENT)
      public IOptionPage getGuiOptionsPage(){
          return new GuiEntityTrackOptions(this);
      }
  
      @Override
      public void initConfig(Configuration config){
          statX = config.get("Helmet_Options" + Configuration.CATEGORY_SPLITTER + "Entity_Tracker", "stat X", -1).getInt();
          statY = config.get("Helmet_Options" + Configuration.CATEGORY_SPLITTER + "Entity_Tracker", "stat Y", 90).getInt();
          statLeftSided = config.get("Helmet_Options" + Configuration.CATEGORY_SPLITTER + "Entity_Tracker", "stat leftsided", true).getBoolean(true);
      }
  
      @Override
      public void saveToConfig(){
          Configuration config = Config.config;
          config.load();
          config.get("Helmet_Options" + Configuration.CATEGORY_SPLITTER + "Entity_Tracker", "stat X", -1).set(entityTrackInfo.getBaseX());
          config.get("Helmet_Options" + Configuration.CATEGORY_SPLITTER + "Entity_Tracker", "stat Y", 90).set(entityTrackInfo.getBaseY());
          config.get("Helmet_Options" + Configuration.CATEGORY_SPLITTER + "Entity_Tracker", "stat leftsided", true).set(entityTrackInfo.isLeftSided());
          statX = entityTrackInfo.getBaseX();
  