package pneumaticCraft.client.render.pneumaticArmor.hacking; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.monster.EntityCaveSpider; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntityEnderman; import net.minecraft.entity.monster.EntityGhast; import net.minecraft.entity.monster.EntityWitch; import net.minecraft.entity.passive.EntityBat; import net.minecraft.entity.passive.EntityCow; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.IExtendedEntityProperties; import pneumaticCraft.PneumaticCraft; import pneumaticCraft.api.PneumaticRegistry; import pneumaticCraft.api.client.pneumaticHelmet.IHackableBlock; import pneumaticCraft.api.client.pneumaticHelmet.IHackableEntity; import pneumaticCraft.client.render.pneumaticArmor.BlockTrackUpgradeHandler; import pneumaticCraft.client.render.pneumaticArmor.EntityTrackUpgradeHandler; import pneumaticCraft.client.render.pneumaticArmor.HUDHandler; import pneumaticCraft.client.render.pneumaticArmor.RenderBlockTarget; import pneumaticCraft.client.render.pneumaticArmor.RenderTarget; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableButton; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableDispenser; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableDoor; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableJukebox; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableLever; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableMobSpawner; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableNoteblock; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableSecurityStation; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableTNT; import pneumaticCraft.client.render.pneumaticArmor.hacking.block.HackableTripwire; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableBat; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableBlaze; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableCaveSpider; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableCow; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableCreeper; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableEnderman; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableGhast; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableLivingDisarm; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableTameable; import pneumaticCraft.client.render.pneumaticArmor.hacking.entity.HackableWitch; import pneumaticCraft.common.PneumaticCraftAPIHandler; import pneumaticCraft.common.block.Blockss; import pneumaticCraft.common.util.WorldAndCoord; import pneumaticCraft.lib.Log; import cpw.mods.fml.relauncher.Side; public class HackableHandler{ private final Map<Entity, IHackableEntity> trackedHackableEntities = new HashMap<Entity, IHackableEntity>(); private final Map<WorldAndCoord, IHackableBlock> trackedHackableBlocks = new HashMap<WorldAndCoord, IHackableBlock>(); private static HackableHandler clientInstance, serverInstance; private static HackableHandler getInstance(){ if(PneumaticCraft.proxy.getSide() == Side.CLIENT) { if(clientInstance == null) clientInstance = new HackableHandler(); return clientInstance; } else { if(serverInstance == null) serverInstance = new HackableHandler(); return serverInstance; } } public static void addDefaultEntries(){ PneumaticRegistry.getInstance().addHackable(Blocks.tnt, HackableTNT.class); PneumaticRegistry.getInstance().addHackable(Blocks.mob_spawner, HackableMobSpawner.class); PneumaticRegistry.getInstance().addHackable(Blocks.lever, HackableLever.class); PneumaticRegistry.getInstance().addHackable(Blocks.stone_button, HackableButton.class); PneumaticRegistry.getInstance().addHackable(Blocks.wooden_button, HackableButton.class); PneumaticRegistry.getInstance().addHackable(Blocks.wooden_door, HackableDoor.class); PneumaticRegistry.getInstance().addHackable(Blocks.tripwire_hook, HackableTripwire.class); PneumaticRegistry.getInstance().addHackable(Blocks.dispenser, HackableDispenser.class); PneumaticRegistry.getInstance().addHackable(Blocks.dropper, HackableDispenser.class); PneumaticRegistry.getInstance().addHackable(Blockss.securityStation, HackableSecurityStation.class); PneumaticRegistry.getInstance().addHackable(Blocks.monster_egg, HackableTripwire.class); PneumaticRegistry.getInstance().addHackable(Blocks.noteblock, HackableNoteblock.class); PneumaticRegistry.getInstance().addHackable(Blocks.jukebox, HackableJukebox.class); PneumaticRegistry.getInstance().addHackable(EntityCreeper.class, HackableCreeper.class); PneumaticRegistry.getInstance().addHackable(EntityTameable.class, HackableTameable.class); PneumaticRegistry.getInstance().addHackable(EntityCow.class, HackableCow.class); PneumaticRegistry.getInstance().addHackable(EntityCaveSpider.class, HackableCaveSpider.class); PneumaticRegistry.getInstance().addHackable(EntityBlaze.class, HackableBlaze.class); PneumaticRegistry.getInstance().addHackable(EntityGhast.class, HackableGhast.class); PneumaticRegistry.getInstance().addHackable(EntityWitch.class, HackableWitch.class); PneumaticRegistry.getInstance().addHackable(EntityLiving.class, HackableLivingDisarm.class); PneumaticRegistry.getInstance().addHackable(EntityEnderman.class, HackableEnderman.class); PneumaticRegistry.getInstance().addHackable(EntityBat.class, HackableBat.class); } public static IHackableEntity getHackableForEntity(Entity entity, EntityPlayer player){ //clean up the map Iterator<Map.Entry<Entity, IHackableEntity>> iterator = getInstance().trackedHackableEntities.entrySet().iterator(); while(iterator.hasNext()) { Map.Entry<Entity, IHackableEntity> entry = iterator.next(); if(entry.getKey().isDead || !entry.getValue().canHack(entry.getKey(), player) && !isInDisplayCooldown(entry.getValue(), entry.getKey())) iterator.remove(); } if(entity instanceof IHackableEntity && ((IHackableEntity)entity).canHack(entity, player)) return (IHackableEntity)entity; IHackableEntity hackable = getInstance().trackedHackableEntities.get(entity); if(hackable == null) { for(Map.Entry<Class<? extends Entity>, Class<? extends IHackableEntity>> entry : PneumaticCraftAPIHandler.getInstance().hackableEntities.entrySet()) { if(entry.getKey().isAssignableFrom(entity.getClass())) { try { hackable = entry.getValue().newInstance(); if(hackable.canHack(entity, player)) { getInstance().trackedHackableEntities.put(entity, hackable); break; } else { hackable = null; } } catch(Exception e) { //shouldn't happen, checked earlier. e.printStackTrace(); } } } } return hackable; } public static IHackableBlock getHackableForCoord(WorldAndCoord coord, EntityPlayer player){ return getHackableForCoord(coord.world, coord.x, coord.y, coord.z, player); } public static IHackableBlock getHackableForCoord(IBlockAccess world, int x, int y, int z, EntityPlayer player){ //clean up the map Iterator<Map.Entry<WorldAndCoord, IHackableBlock>> iterator = getInstance().trackedHackableBlocks.entrySet().iterator(); while(iterator.hasNext()) { Map.Entry<WorldAndCoord, IHackableBlock> entry = iterator.next(); Class<? extends IHackableBlock> hackableBlockClazz = PneumaticCraftAPIHandler.getInstance().hackableBlocks.get(entry.getKey().getBlock()); if(hackableBlockClazz != entry.getValue().getClass() || !entry.getValue().canHack(entry.getKey().world, entry.getKey().x, entry.getKey().y, entry.getKey().z, player) && !isInDisplayCooldown(entry.getValue(), entry.getKey().world, entry.getKey().x, entry.getKey().y, entry.getKey().z, player)) iterator.remove(); } Block block = world.getBlock(x, y, z); if(block instanceof IHackableBlock && ((IHackableBlock)block).canHack(world, x, y, z, player)) return (IHackableBlock)block; IHackableBlock hackable = getInstance().trackedHackableBlocks.get(new WorldAndCoord(world, x, y, z)); if(hackable == null) { if(!PneumaticCraftAPIHandler.getInstance().hackableBlocks.containsKey(block)) return null; try { hackable = PneumaticCraftAPIHandler.getInstance().hackableBlocks.get(block).newInstance(); if(hackable.canHack(world, x, y, z, player)) { getInstance().trackedHackableBlocks.put(new WorldAndCoord(world, x, y, z), hackable); } else { hackable = null; } } catch(Exception e) { //shouldn't happen, checked earlier. e.printStackTrace(); } } return hackable; } private static boolean isInDisplayCooldown(IHackableBlock hackableBlock, IBlockAccess world, int x, int y, int z, EntityPlayer player){ if(player.worldObj.isRemote) { RenderBlockTarget target = HUDHandler.instance().getSpecificRenderer(BlockTrackUpgradeHandler.class).getTargetForCoord(x, y, z); int requiredHackTime = hackableBlock.getHackTime(world, x, y, z, player); return target != null && target.getHackTime() >= requiredHackTime && target.getHackTime() <= requiredHackTime + 20; } else { return false; } } private static boolean isInDisplayCooldown(IHackableEntity hackableBlock, Entity entity){ if(entity.worldObj.isRemote) { RenderTarget target = HUDHandler.instance().getSpecificRenderer(EntityTrackUpgradeHandler.class).getTargetForEntity(entity); int requiredHackTime = hackableBlock.getHackTime(entity, PneumaticCraft.proxy.getPlayer()); return target != null && target.getHackTime() >= requiredHackTime && target.getHackTime() <= requiredHackTime + 20; } else { return false; } } public static void onEntityConstruction(Entity entity){ entity.registerExtendedProperties("PneumaticCraftHacking", new HackingEntityProperties()); } public static class HackingEntityProperties implements IExtendedEntityProperties{ private List<IHackableEntity> hackables; @Override public void saveNBTData(NBTTagCompound compound){ if(hackables != null && !hackables.isEmpty()) { NBTTagList tagList = new NBTTagList(); for(IHackableEntity hackableEntity : hackables) { if(hackableEntity.getId() != null) { NBTTagCompound tag = new NBTTagCompound(); tag.setString("id", hackableEntity.getId()); tagList.appendTag(tag); } } compound.setTag("hackables", tagList); } } @Override public void loadNBTData(NBTTagCompound compound){ hackables = null; NBTTagList tagList = compound.getTagList("hackables", 10); for(int i = 0; i < tagList.tagCount(); i++) { String hackableId = tagList.getCompoundTagAt(i).getString("id"); Class<? extends IHackableEntity> hackableClass = PneumaticCraftAPIHandler.getInstance().stringToEntityHackables.get(hackableId); if(hackableClass != null) { try { if(hackables == null) hackables = new ArrayList<IHackableEntity>(); hackables.add(hackableClass.newInstance()); } catch(Exception e) { e.printStackTrace(); } } else { Log.warning("hackable \"" + hackableId + "\" not found when constructing from nbt. Was it deleted?"); } } } @Override public void init(Entity entity, World world){} public void update(Entity entity){ if(hackables != null) { Iterator<IHackableEntity> iterator = hackables.iterator(); while(iterator.hasNext()) { IHackableEntity hackable = iterator.next(); if(!hackable.afterHackTick(entity)) { iterator.remove(); } } } } public void addHackable(IHackableEntity hackable){ if(hackables == null) hackables = new ArrayList<IHackableEntity>(); hackables.add(hackable); } public List<IHackableEntity> getCurrentHacks(){ return hackables; } } }