/** * This class was created by <Vazkii>. It's distributed as * part of the Botania Mod. Get the Source Code in github: * https://github.com/Vazkii/Botania * * Botania is Open Source and distributed under the * Botania License: http://botaniamod.net/license.php * * File Created @ [Feb 16, 2014, 12:37:40 AM (GMT)] */ package vazkii.botania.common.block.subtile.functional; import java.util.ArrayList; import java.util.List; import com.google.common.base.Predicates; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAIAttackMelee; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAITasks.EntityAITaskEntry; import net.minecraft.entity.monster.IMob; import net.minecraft.util.math.AxisAlignedBB; import net.minecraftforge.fml.relauncher.ReflectionHelper; import vazkii.botania.api.lexicon.LexiconEntry; import vazkii.botania.api.subtile.RadiusDescriptor; import vazkii.botania.api.subtile.SubTileFunctional; import vazkii.botania.common.lexicon.LexiconData; import vazkii.botania.common.lib.LibObfuscation; public class SubTileHeiseiDream extends SubTileFunctional { private static final int RANGE = 5; @Override public void onUpdate() { super.onUpdate(); if(supertile.getWorld().isRemote) return; final int cost = 100; @SuppressWarnings("unchecked") List<IMob> mobs = (List) supertile.getWorld().getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(supertile.getPos().add(-RANGE, -RANGE, -RANGE), supertile.getPos().add(RANGE + 1, RANGE + 1, RANGE + 1)), Predicates.instanceOf(IMob.class)); if(mobs.size() > 1 && mana >= cost) for(IMob mob : mobs) { if(mob instanceof EntityLiving) { EntityLiving entity = (EntityLiving) mob; if(brainwashEntity(entity, mobs)) { mana -= cost; sync(); break; } } } } public static boolean brainwashEntity(EntityLiving entity, List<IMob> mobs) { EntityLivingBase target = entity.getAttackTarget(); boolean did = false; if(target == null || !(target instanceof IMob)) { IMob newTarget; do newTarget = mobs.get(entity.world.rand.nextInt(mobs.size())); while(newTarget == entity); if(newTarget instanceof EntityLiving) { List<EntityAITaskEntry> entries = new ArrayList<>(entity.tasks.taskEntries); entries.addAll(new ArrayList<>(entity.targetTasks.taskEntries)); for(EntityAITaskEntry entry : entries) if(entry.action instanceof EntityAINearestAttackableTarget) { messWithGetTargetAI((EntityAINearestAttackableTarget) entry.action, (EntityLiving) newTarget); did = true; } else if(entry.action instanceof EntityAIAttackMelee) { did = true; } if(did) entity.setAttackTarget((EntityLiving) newTarget); } } return did; } private static void messWithGetTargetAI(EntityAINearestAttackableTarget aiEntry, EntityLivingBase target) { ReflectionHelper.setPrivateValue(EntityAINearestAttackableTarget.class, aiEntry, Entity.class, LibObfuscation.TARGET_CLASS); ReflectionHelper.setPrivateValue(EntityAINearestAttackableTarget.class, aiEntry, Predicates.equalTo(target), LibObfuscation.TARGET_ENTITY_SELECTOR); // todo 1.8 will this leak `target`? } @Override public RadiusDescriptor getRadius() { return new RadiusDescriptor.Square(toBlockPos(), RANGE); } @Override public int getColor() { return 0xFF219D; } @Override public int getMaxMana() { return 1000; } @Override public LexiconEntry getEntry() { return LexiconData.heiseiDream; } }