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(); statY = entityTrackInfo.getBaseY(); statLeftSided = entityTrackInfo.isLeftSided(); config.save(); } @Override @SideOnly(Side.CLIENT) public GuiAnimatedStat getAnimatedStat(){ if(entityTrackInfo == null) { Minecraft minecraft = Minecraft.getMinecraft(); ScaledResolution sr = new ScaledResolution(minecraft, minecraft.displayWidth, minecraft.displayHeight); entityTrackInfo = new GuiAnimatedStat(null, "Current tracked entities:", new ItemStack(Itemss.machineUpgrade, 1, ItemMachineUpgrade.UPGRADE_ENTITY_TRACKER), statX != -1 ? statX : sr.getScaledWidth() - 2, statY, 0x3000AA00, null, statLeftSided); entityTrackInfo.setMinDimensionsAndReset(0, 0); } return entityTrackInfo; } public List<RenderTarget> getTargets(){ return targets; } public RenderTarget getTargetForEntity(Entity entity){ for(RenderTarget target : targets) { if(target.entity == entity) { return target; } } return null; } public void hack(){ for(RenderTarget target : targets) { target.hack(); } } public void selectAsDebuggingTarget(){ for(RenderTarget target : targets) { target.selectAsDebuggingTarget(); } } public boolean scroll(MouseEvent event){ for(RenderTarget target : targets) { if(target.scroll(event)) return true; } return false; } }