vazkii.botania.common.block.subtile.functional.SubTileHeiseiDream.java Source code

Java tutorial

Introduction

Here is the source code for vazkii.botania.common.block.subtile.functional.SubTileHeiseiDream.java

Source

/**
 * 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.worldObj.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;
    }

}