Package vazkii.botania.common.entity

Source Code of vazkii.botania.common.entity.EntityManaBurst$PositionProperties

/**
* 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 a
* Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License
* (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB)
*
* File Created @ [Jan 26, 2014, 5:09:12 PM (GMT)]
*/
package vazkii.botania.common.entity;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import buildcraft.api.transport.IPipeTile;
import cpw.mods.fml.common.Loader;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBush;
import net.minecraft.block.BlockLeaves;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.internal.IManaBurst;
import vazkii.botania.api.mana.IClientManaHandler;
import vazkii.botania.api.mana.ILensEffect;
import vazkii.botania.api.mana.IManaCollector;
import vazkii.botania.api.mana.IManaCollisionGhost;
import vazkii.botania.api.mana.IManaReceiver;
import vazkii.botania.api.mana.IManaTrigger;
import vazkii.botania.common.Botania;
import vazkii.botania.common.block.tile.mana.TileSpreader;
import vazkii.botania.common.core.handler.ConfigHandler;
import vazkii.botania.common.core.helper.Vector3;
import vazkii.botania.common.item.equipment.bauble.ItemTinyPlanet;

public class EntityManaBurst extends EntityThrowable implements IManaBurst {

  private static final String TAG_TICKS_EXISTED = "ticksExisted";
  private static final String TAG_COLOR = "color";
  private static final String TAG_MANA = "mana";
  private static final String TAG_STARTING_MANA = "startingMana";
  private static final String TAG_MIN_MANA_LOSS = "minManaLoss";
  private static final String TAG_TICK_MANA_LOSS = "manaLossTick";
  private static final String TAG_SPREADER_X = "spreaderX";
  private static final String TAG_SPREADER_Y = "spreaderY";
  private static final String TAG_SPREADER_Z = "spreaderZ";
  private static final String TAG_GRAVITY = "gravity";
  private static final String TAG_LENS_STACK = "lensStack";
  private static final String TAG_LAST_MOTION_X = "lastMotionX";
  private static final String TAG_LAST_MOTION_Y = "lastMotionY";
  private static final String TAG_LAST_MOTION_Z = "lastMotionZ";

  boolean fake = false;

  final int dataWatcherEntries = 10;
  final int dataWatcherStart = 32 - dataWatcherEntries;

  List<String> alreadyCollidedAt = new ArrayList();

  boolean fullManaLastTick = true;

  int _ticksExisted = 0;
  boolean scanBeam = false;
  public List<PositionProperties> propsList = new ArrayList();

  public EntityManaBurst(World world) {
    super(world);
    setSize(0F, 0F);
    for(int i = 0; i < dataWatcherEntries; i++) {
      int j = dataWatcherStart + i;
      if(i == 4 || i == 5)
        dataWatcher.addObject(j, 0F);
      else if(i == 9)
        dataWatcher.addObject(j, new ItemStack(Blocks.stone, 0, 0));
      else dataWatcher.addObject(j, 0);

      dataWatcher.setObjectWatched(j);
    }
  }

  public EntityManaBurst(TileSpreader spreader, boolean fake) {
    this(spreader.getWorldObj());
    this.fake = fake;

    setBurstSourceCoords(spreader.xCoord, spreader.yCoord, spreader.zCoord);
    setLocationAndAngles(spreader.xCoord + 0.5, spreader.yCoord + 0.5, spreader.zCoord + 0.5, 0, 0);
    rotationYaw = -(spreader.rotationX + 90F);
    rotationPitch = spreader.rotationY;

    float f = 0.4F;
    double mx = MathHelper.sin(rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(rotationPitch / 180.0F * (float) Math.PI) * f / 2D;
    double mz = -(MathHelper.cos(rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(rotationPitch / 180.0F * (float) Math.PI) * f) / 2D;
    double my = MathHelper.sin((rotationPitch + func_70183_g()) / 180.0F * (float) Math.PI) * f / 2D;
    setMotion(mx, my, mz);
  }

  public EntityManaBurst(EntityPlayer player) {
    this(player.worldObj);

    setBurstSourceCoords(0, -1, 0);
    setLocationAndAngles(player.posX, player.posY + player.getEyeHeight(), player.posZ, player.rotationYaw + 180, -player.rotationPitch);

    posX -= MathHelper.cos((rotationYaw + 180) / 180.0F * (float) Math.PI) * 0.16F;
    posY -= 0.10000000149011612D;
    posZ -= MathHelper.sin((rotationYaw + 180) / 180.0F * (float) Math.PI) * 0.16F;

    setPosition(posX, posY, posZ);
    yOffset = 0.0F;
    float f = 0.4F;
    double mx = MathHelper.sin(rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(rotationPitch / 180.0F * (float) Math.PI) * f / 2D;
    double mz = -(MathHelper.cos(rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(rotationPitch / 180.0F * (float) Math.PI) * f) / 2D;
    double my = MathHelper.sin((rotationPitch + func_70183_g()) / 180.0F * (float) Math.PI) * f / 2D;
    setMotion(mx, my, mz);
  }

  float accumulatedManaLoss = 0;

  private int ticksInAir;

  // Hacked code copied from super.onUpdate, to use Vector3 rather than the world vector pool
  public void superUpdate() {
    lastTickPosX = posX;
    lastTickPosY = posY;
    lastTickPosZ = posZ;
    onEntityUpdate();

    if(throwableShake > 0)
      --throwableShake;

    Vec3 vec3 = new Vector3(posX, posY, posZ).toVec3D();
    Vec3 vec31 = new Vector3(posX + motionX, posY + motionY, posZ + motionZ).toVec3D();
    MovingObjectPosition movingobjectposition = clip(vec3, vec31);

    if(movingobjectposition != null)
      vec31 = new Vector3(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord).toVec3D();

    if(!worldObj.isRemote) {
      Entity entity = null;
      List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.addCoord(motionX, motionY, motionZ).expand(1.0D, 1.0D, 1.0D));
      double d0 = 0.0D;
      EntityLivingBase entitylivingbase = getThrower();

      for(int j = 0; j < list.size(); ++j) {
        Entity entity1 = (Entity) list.get(j);

        if(entity1.canBeCollidedWith() && (entity1 != entitylivingbase || ticksInAir >= 5)) {
          float f = 0.3F;
          AxisAlignedBB axisalignedbb = entity1.boundingBox.expand(f, f, f);
          MovingObjectPosition movingobjectposition1 = axisalignedbb.calculateIntercept(vec3, vec31);

          if(movingobjectposition1 != null) {
            double d1 = vec3.distanceTo(movingobjectposition1.hitVec);

            if (d1 < d0 || d0 == 0.0D) {
              entity = entity1;
              d0 = d1;
            }
          }
        }
      }

      if(entity != null)
        movingobjectposition = new MovingObjectPosition(entity);
    }

    if(movingobjectposition != null)
      onImpact(movingobjectposition);

    posX += motionX;
    posY += motionY;
    posZ += motionZ;
    float f1 = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ);
    rotationYaw = (float)(Math.atan2(motionX, motionZ) * 180.0D / Math.PI);

    for(rotationPitch = (float)(Math.atan2(motionY, f1) * 180.0D / Math.PI); rotationPitch - prevRotationPitch < -180.0F; prevRotationPitch -= 360.0F);

    while(rotationPitch - prevRotationPitch >= 180.0F)
      prevRotationPitch += 360.0F;

    while(rotationYaw - prevRotationYaw < -180.0F)
      prevRotationYaw -= 360.0F;

    while(rotationYaw - prevRotationYaw >= 180.0F)
      prevRotationYaw += 360.0F;

    rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2F;
    rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2F;
    float f3 = getGravityVelocity();

    motionY -= f3;
    setPosition(posX, posY, posZ);
  }

  public MovingObjectPosition clip(Vec3 par1Vec3, Vec3 par2Vec3) {
    boolean par3 = false;
    boolean par4 = false;
    if (!Double.isNaN(par1Vec3.xCoord) && !Double.isNaN(par1Vec3.yCoord) && !Double.isNaN(par1Vec3.zCoord)) {
      if (!Double.isNaN(par2Vec3.xCoord) && !Double.isNaN(par2Vec3.yCoord) && !Double.isNaN(par2Vec3.zCoord)) {
        int i = MathHelper.floor_double(par2Vec3.xCoord);
        int j = MathHelper.floor_double(par2Vec3.yCoord);
        int k = MathHelper.floor_double(par2Vec3.zCoord);
        int l = MathHelper.floor_double(par1Vec3.xCoord);
        int i1 = MathHelper.floor_double(par1Vec3.yCoord);
        int j1 = MathHelper.floor_double(par1Vec3.zCoord);
        Block block = worldObj.getBlock(l, i1, j1);
        int l1 = worldObj.getBlockMetadata(l, i1, j1);

        if (block != null && (!par4 || block == null || block.getCollisionBoundingBoxFromPool(worldObj, l, i1, j1) != null) && block != Blocks.air && block.canCollideCheck(l1, par3)) {
          MovingObjectPosition movingobjectposition = block.collisionRayTrace(worldObj, l, i1, j1, par1Vec3, par2Vec3);

          if (movingobjectposition != null)
            return movingobjectposition;
        }

        int k1 = 200;

        while (k1-- >= 0) {
          if (Double.isNaN(par1Vec3.xCoord) || Double.isNaN(par1Vec3.yCoord) || Double.isNaN(par1Vec3.zCoord))
            return null;

          if (l == i && i1 == j && j1 == k)
            return null;

          boolean flag2 = true;
          boolean flag3 = true;
          boolean flag4 = true;
          double d0 = 999.0D;
          double d1 = 999.0D;
          double d2 = 999.0D;

          if (i > l)
            d0 = l + 1.0D;
          else if (i < l)
            d0 = l + 0.0D;
          else flag2 = false;

          if (j > i1)
            d1 = i1 + 1.0D;
          else if (j < i1)
            d1 = i1 + 0.0D;
          else flag3 = false;

          if (k > j1)
            d2 = j1 + 1.0D;
          else if (k < j1)
            d2 = j1 + 0.0D;
          else flag4 = false;

          double d3 = 999.0D;
          double d4 = 999.0D;
          double d5 = 999.0D;
          double d6 = par2Vec3.xCoord - par1Vec3.xCoord;
          double d7 = par2Vec3.yCoord - par1Vec3.yCoord;
          double d8 = par2Vec3.zCoord - par1Vec3.zCoord;

          if (flag2)
            d3 = (d0 - par1Vec3.xCoord) / d6;

          if (flag3)
            d4 = (d1 - par1Vec3.yCoord) / d7;

          if (flag4)
            d5 = (d2 - par1Vec3.zCoord) / d8;

          byte b0;

          if (d3 < d4 && d3 < d5) {
            if (i > l)
              b0 = 4;
            else b0 = 5;

            par1Vec3.xCoord = d0;
            par1Vec3.yCoord += d7 * d3;
            par1Vec3.zCoord += d8 * d3;
          } else if (d4 < d5) {
            if (j > i1)
              b0 = 0;
            else b0 = 1;

            par1Vec3.xCoord += d6 * d4;
            par1Vec3.yCoord = d1;
            par1Vec3.zCoord += d8 * d4;
          } else {
            if (k > j1)
              b0 = 2;
            else b0 = 3;

            par1Vec3.xCoord += d6 * d5;
            par1Vec3.yCoord += d7 * d5;
            par1Vec3.zCoord = d2;
          }

          Vec3 vec32 = new Vector3(par1Vec3.xCoord, par1Vec3.yCoord, par1Vec3.zCoord).toVec3D();
          l = (int)(vec32.xCoord = MathHelper.floor_double(par1Vec3.xCoord));

          if (b0 == 5) {
            --l;
            ++vec32.xCoord;
          }

          i1 = (int)(vec32.yCoord = MathHelper.floor_double(par1Vec3.yCoord));

          if (b0 == 1) {
            --i1;
            ++vec32.yCoord;
          }

          j1 = (int)(vec32.zCoord = MathHelper.floor_double(par1Vec3.zCoord));

          if (b0 == 3) {
            --j1;
            ++vec32.zCoord;
          }

          Block block1 = worldObj.getBlock(l, i1, j1);
          int j2 = worldObj.getBlockMetadata(l, i1, j1);

          if ((!par4 || block1 == null || block1.getCollisionBoundingBoxFromPool(worldObj, l, i1, j1) != null) && block1 != Blocks.air && block1.canCollideCheck(j2, par3)) {
            MovingObjectPosition movingobjectposition1 = block1.collisionRayTrace(worldObj, l, i1, j1, par1Vec3, par2Vec3);

            if (movingobjectposition1 != null)
              return movingobjectposition1;
          }
        }

        return null;
      }
      else return null;
    } else return null;
  }

  @Override
  public void onUpdate() {
    setTicksExisted(getTicksExisted() + 1);
    superUpdate();

    if(!fake && !isDead) {
      ChunkCoordinates coords = getBurstSourceChunkCoordinates();
      TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ);
      if(tile != null && tile instanceof TileSpreader)
        ((TileSpreader) tile).canShootBurst = false;
    }

    ILensEffect lens = getLensInstance();
    if(lens != null)
      lens.updateBurst(this, getSourceLens());

    int mana = getMana();
    if(getTicksExisted() >= getMinManaLoss()) {
      accumulatedManaLoss += getManaLossPerTick();
      int loss = (int) accumulatedManaLoss;
      setMana(mana - loss);
      accumulatedManaLoss -= loss;

      if(getMana() <= 0)
        setDead();
    }

    particles();

    setMotion(motionX, motionY, motionZ);

    fullManaLastTick = getMana() == getStartingMana();

    if(scanBeam) {
      PositionProperties props = new PositionProperties(this);
      if(propsList.isEmpty())
        propsList.add(props);
      else {
        PositionProperties lastProps = propsList.get(propsList.size() - 1);
        if(!props.coordsEqual(lastProps))
          propsList.add(props);
      }
    }
  }

  @Override
  public boolean handleWaterMovement() {
    return false;
  }

  TileEntity collidedTile = null;
  boolean noParticles = false;

  public TileEntity getCollidedTile(boolean noParticles) {
    this.noParticles = noParticles;

    while(!isDead)
      onUpdate();

    if(fake)
      incrementFakeParticleTick();

    return collidedTile;
  }

  @Override
  public void writeEntityToNBT(NBTTagCompound par1nbtTagCompound) {
    super.writeEntityToNBT(par1nbtTagCompound);
    par1nbtTagCompound.setInteger(TAG_TICKS_EXISTED, getTicksExisted());
    par1nbtTagCompound.setInteger(TAG_COLOR, getColor());
    par1nbtTagCompound.setInteger(TAG_MANA, getMana());
    par1nbtTagCompound.setInteger(TAG_STARTING_MANA, getStartingMana());
    par1nbtTagCompound.setInteger(TAG_MIN_MANA_LOSS, getMinManaLoss());
    par1nbtTagCompound.setFloat(TAG_TICK_MANA_LOSS, getManaLossPerTick());
    par1nbtTagCompound.setFloat(TAG_GRAVITY, getGravity());

    ItemStack stack = getSourceLens();
    NBTTagCompound lensCmp = new NBTTagCompound();
    if(stack != null)
      stack.writeToNBT(lensCmp);
    par1nbtTagCompound.setTag(TAG_LENS_STACK, lensCmp);

    ChunkCoordinates coords = getBurstSourceChunkCoordinates();
    par1nbtTagCompound.setInteger(TAG_SPREADER_X, coords.posX);
    par1nbtTagCompound.setInteger(TAG_SPREADER_Y, coords.posY);
    par1nbtTagCompound.setInteger(TAG_SPREADER_Z, coords.posZ);

    par1nbtTagCompound.setDouble(TAG_LAST_MOTION_X, motionX);
    par1nbtTagCompound.setDouble(TAG_LAST_MOTION_Y, motionY);
    par1nbtTagCompound.setDouble(TAG_LAST_MOTION_Z, motionZ);
  }

  @Override
  public void readEntityFromNBT(NBTTagCompound par1nbtTagCompound) {
    super.readEntityFromNBT(par1nbtTagCompound);
    setTicksExisted(par1nbtTagCompound.getInteger(TAG_TICKS_EXISTED));
    setColor(par1nbtTagCompound.getInteger(TAG_COLOR));
    setMana(par1nbtTagCompound.getInteger(TAG_MANA));
    setStartingMana(par1nbtTagCompound.getInteger(TAG_STARTING_MANA));
    setMinManaLoss(par1nbtTagCompound.getInteger(TAG_MIN_MANA_LOSS));
    setManaLossPerTick(par1nbtTagCompound.getFloat(TAG_TICK_MANA_LOSS));
    setGravity(par1nbtTagCompound.getFloat(TAG_GRAVITY));

    NBTTagCompound lensCmp = par1nbtTagCompound.getCompoundTag(TAG_LENS_STACK);
    ItemStack stack = ItemStack.loadItemStackFromNBT(lensCmp);
    if(stack != null)
      setSourceLens(stack);
    else setSourceLens(new ItemStack(Blocks.stone, 0, 0));

    int x = par1nbtTagCompound.getInteger(TAG_SPREADER_X);
    int y = par1nbtTagCompound.getInteger(TAG_SPREADER_Y);
    int z = par1nbtTagCompound.getInteger(TAG_SPREADER_Z);

    setBurstSourceCoords(x, y, z);

    double lastMotionX = par1nbtTagCompound.getDouble(TAG_LAST_MOTION_X);
    double lastMotionY = par1nbtTagCompound.getDouble(TAG_LAST_MOTION_Y);
    double lastMotionZ = par1nbtTagCompound.getDouble(TAG_LAST_MOTION_Z);

    setMotion(lastMotionX, lastMotionY, lastMotionZ);
  }

  public void particles() {
    if(isDead || !worldObj.isRemote)
      return;

    ILensEffect lens = getLensInstance();
    if(lens != null && !lens.doParticles(this, getSourceLens()))
      return;

    Color color = new Color(getColor());
    float r = color.getRed() / 255F;
    float g = color.getGreen() / 255F;
    float b = color.getBlue() / 255F;

    int mana = getMana();
    int maxMana = getStartingMana();
    float osize = (float) mana / (float) maxMana;
    float size = osize;

    if(fake) {
      if(getMana() == getStartingMana())
        size = 2F;
      else if(fullManaLastTick)
        size = 4F;

      if(!noParticles && shouldDoFakeParticles())
        Botania.proxy.sparkleFX(worldObj, posX, posY, posZ, r, g, b, 0.4F * size, 1, true);
    } else {
      if(ConfigHandler.subtlePowerSystem)
        Botania.proxy.wispFX(worldObj, posX, posY, posZ, r, g, b, 0.1F * size, (float) (Math.random() - 0.5F) * 0.02F, (float) (Math.random() - 0.5F) * 0.02F, (float) (Math.random() - 0.5F) * 0.01F);
      else {
        float or = r;
        float og = g;
        float ob = b;

        double savedPosX = posX;
        double savedPosY = posY;
        double savedPosZ = posZ;

        Vector3 currentPos = Vector3.fromEntity(this);
        Vector3 oldPos = new Vector3(prevPosX, prevPosY, prevPosZ);
        Vector3 diffVec = oldPos.copy().sub(currentPos);
        Vector3 diffVecNorm = diffVec.copy().normalize();

        double distance = 0.095;

        do {
          r = or + ((float) Math.random() - 0.5F) * 0.25F;
          g = og + ((float) Math.random() - 0.5F) * 0.25F;
          b = ob + ((float) Math.random() - 0.5F) * 0.25F;
          size = osize + ((float) Math.random() - 0.5F) * 0.065F + (float) Math.sin(new Random(entityUniqueID.getMostSignificantBits()).nextInt(9001)) * 0.4F;
          Botania.proxy.wispFX(worldObj, posX, posY, posZ, r, g, b, 0.2F * size, (float) -motionX * 0.01F, (float) -motionY * 0.01F, (float) -motionZ * 0.01F);

          posX += diffVecNorm.x * distance;
          posY += diffVecNorm.y * distance;
          posZ += diffVecNorm.z * distance;

          currentPos = Vector3.fromEntity(this);
          diffVec = oldPos.copy().sub(currentPos);
          if(getEntityData().hasKey(ItemTinyPlanet.TAG_ORBIT))
            break;
        } while(Math.abs(diffVec.mag()) > distance);

        Botania.proxy.wispFX(worldObj, posX, posY, posZ, r, g, b, 0.1F * size, (float) (Math.random() - 0.5F) * 0.06F, (float) (Math.random() - 0.5F) * 0.06F, (float) (Math.random() - 0.5F) * 0.06F);

        posX = savedPosX;
        posY = savedPosY;
        posZ = savedPosZ;
      }
    }
  }

  @Override
  protected void onImpact(MovingObjectPosition movingobjectposition) {
    boolean collided = false;
    boolean dead = false;

    if(movingobjectposition.entityHit == null) {
      TileEntity tile = worldObj.getTileEntity(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);
      Block block = worldObj.getBlock(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);

      if(tile instanceof IManaCollisionGhost && ((IManaCollisionGhost) tile).isGhost() || block instanceof BlockBush || block instanceof BlockLeaves)
        return;

      if(BotaniaAPI.internalHandler.isBuildcraftPipe(tile))
        return;
     
      ChunkCoordinates coords = getBurstSourceChunkCoordinates();
      if(tile != null && (tile.xCoord != coords.posX || tile.yCoord != coords.posY || tile.zCoord != coords.posZ))
        collidedTile = tile;

      if(tile == null || tile.xCoord != coords.posX || tile.yCoord != coords.posY || tile.zCoord != coords.posZ) {
        if(!fake && !noParticles && (!worldObj.isRemote || tile instanceof IClientManaHandler) && tile != null && tile instanceof IManaReceiver && ((IManaReceiver) tile).canRecieveManaFromBursts()) {
          int mana = getMana();
          if(tile instanceof IManaCollector)
            mana *= ((IManaCollector) tile).getManaYieldMultiplier(this);

          ((IManaReceiver) tile).recieveMana(mana);
          worldObj.markBlockForUpdate(tile.xCoord, tile.yCoord, tile.zCoord);
        }

        if(!isFake() && block instanceof IManaTrigger)
          ((IManaTrigger) block).onBurstCollision(this, worldObj, movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);

        dead = true;
      }

      collided = true;
    }

    ILensEffect lens = getLensInstance();
    if(lens != null)
      dead = lens.collideBurst(this, movingobjectposition, collidedTile != null && collidedTile instanceof IManaReceiver && ((IManaReceiver) collidedTile).canRecieveManaFromBursts(), dead, getSourceLens());

    if(collided && !hasAlreadyCollidedAt(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ))
      alreadyCollidedAt.add(getCollisionLocString(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ));

    if(dead && !isDead) {
      if(!fake) {
        Color color = new Color(getColor());
        float r = color.getRed() / 255F;
        float g = color.getGreen() / 255F;
        float b = color.getBlue() / 255F;

        int mana = getMana();
        int maxMana = getStartingMana();
        float size = (float) mana / (float) maxMana;

        if(!ConfigHandler.subtlePowerSystem)
          for(int i = 0; i < 4; i++)
            Botania.proxy.wispFX(worldObj, posX, posY, posZ, r, g, b, 0.15F * size, (float) (Math.random() - 0.5F) * 0.04F, (float) (Math.random() - 0.5F) * 0.04F, (float) (Math.random() - 0.5F) * 0.04F);
        Botania.proxy.sparkleFX(worldObj, (float) posX, (float) posY, (float) posZ, r, g, b, 4, 2);
      }

      setDead();
    }
  }

  @Override
  public void setDead() {
    super.setDead();

    if(!fake) {
      ChunkCoordinates coords = getBurstSourceChunkCoordinates();
      TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ);
      if(tile != null && tile instanceof TileSpreader)
        ((TileSpreader) tile).canShootBurst = true;
    } else setDeathTicksForFakeParticle();
  }

  @Override
  protected float getGravityVelocity() {
    return getGravity();
  }

  @Override
  public boolean isFake() {
    return fake;
  }

  public void setScanBeam() {
    scanBeam = true;
  }

  @Override
  public int getColor() {
    return dataWatcher.getWatchableObjectInt(dataWatcherStart);
  }

  @Override
  public void setColor(int color) {
    dataWatcher.updateObject(dataWatcherStart, color);
  }

  @Override
  public int getMana() {
    return dataWatcher.getWatchableObjectInt(dataWatcherStart + 1);
  }

  @Override
  public void setMana(int mana) {
    dataWatcher.updateObject(dataWatcherStart + 1, mana);
  }

  @Override
  public int getStartingMana() {
    return dataWatcher.getWatchableObjectInt(dataWatcherStart + 2);
  }

  @Override
  public void setStartingMana(int mana) {
    dataWatcher.updateObject(dataWatcherStart + 2, mana);
  }

  @Override
  public int getMinManaLoss() {
    return dataWatcher.getWatchableObjectInt(dataWatcherStart + 3);
  }

  @Override
  public void setMinManaLoss(int minManaLoss) {
    dataWatcher.updateObject(dataWatcherStart + 3, minManaLoss);
  }

  @Override
  public float getManaLossPerTick() {
    return dataWatcher.getWatchableObjectFloat(dataWatcherStart + 4);
  }

  @Override
  public void setManaLossPerTick(float mana) {
    dataWatcher.updateObject(dataWatcherStart + 4, mana);
  }

  @Override
  public float getGravity() {
    return dataWatcher.getWatchableObjectFloat(dataWatcherStart + 5);
  }

  @Override
  public void setGravity(float gravity) {
    dataWatcher.updateObject(dataWatcherStart + 5, gravity);
  }

  final int coordsStart = dataWatcherStart + 6;

  @Override
  public ChunkCoordinates getBurstSourceChunkCoordinates() {
    int x = dataWatcher.getWatchableObjectInt(coordsStart);
    int y = dataWatcher.getWatchableObjectInt(coordsStart + 1);
    int z = dataWatcher.getWatchableObjectInt(coordsStart + 2);

    return new ChunkCoordinates(x, y, z);
  }

  @Override
  public void setBurstSourceCoords(int x, int y, int z) {
    dataWatcher.updateObject(coordsStart, x);
    dataWatcher.updateObject(coordsStart + 1, y);
    dataWatcher.updateObject(coordsStart + 2, z);
  }

  @Override
  public ItemStack getSourceLens() {
    return dataWatcher.getWatchableObjectItemStack(dataWatcherStart + 9);
  }

  @Override
  public void setSourceLens(ItemStack lens) {
    dataWatcher.updateObject(dataWatcherStart + 9, lens == null ? new ItemStack(Blocks.stone, 0, 0) : lens);
  }

  @Override
  public int getTicksExisted() {
    return _ticksExisted;
  }

  public void setTicksExisted(int ticks) {
    _ticksExisted = ticks;
  }

  public ILensEffect getLensInstance() {
    ItemStack lens = getSourceLens();
    if(lens != null && lens.getItem() instanceof ILensEffect)
      return (ILensEffect) lens.getItem();

    return null;
  }

  final int motionStart = dataWatcherStart + 10;

  @Override
  public void setMotion(double x, double y, double z) {
    motionX = x;
    motionY = y;
    motionZ = z;
  }

  @Override
  public boolean hasAlreadyCollidedAt(int x, int y, int z) {
    return alreadyCollidedAt.contains(getCollisionLocString(x, y, z));
  }

  private String getCollisionLocString(int x, int y, int z) {
    return x + ":" + y + ":" + z;
  }

  private boolean shouldDoFakeParticles() {
    if(ConfigHandler.staticWandBeam)
      return true;

    ChunkCoordinates coords = getBurstSourceChunkCoordinates();
    TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ);
    if(tile != null && tile instanceof TileSpreader)
      return getMana() != getStartingMana() && fullManaLastTick || Math.abs(((TileSpreader) tile).burstParticleTick - getTicksExisted()) < 4;
    return false;
  }

  private void incrementFakeParticleTick() {
    ChunkCoordinates coords = getBurstSourceChunkCoordinates();
    TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ);
    if(tile != null && tile instanceof TileSpreader) {
      TileSpreader spreader = (TileSpreader) tile;
      spreader.burstParticleTick += 2;
      if(spreader.lastBurstDeathTick != -1 && spreader.burstParticleTick > spreader.lastBurstDeathTick)
        spreader.burstParticleTick = 0;
    }
  }

  private void setDeathTicksForFakeParticle() {
    ChunkCoordinates coords = getBurstSourceChunkCoordinates();
    TileEntity tile = worldObj.getTileEntity(coords.posX, coords.posY, coords.posZ);
    if(tile != null && tile instanceof TileSpreader)
      ((TileSpreader) tile).lastBurstDeathTick = getTicksExisted();
  }

  public static class PositionProperties {

    public final ChunkCoordinates coords;
    public final Block block;
    public final int meta;

    public PositionProperties(Entity entity) {
      int x = MathHelper.floor_double(entity.posX);
      int y = MathHelper.floor_double(entity.posY);
      int z = MathHelper.floor_double(entity.posZ);
      coords = new ChunkCoordinates(x, y, z);
      block = entity.worldObj.getBlock(x, y, z);
      meta = entity.worldObj.getBlockMetadata(x, y, z);
    }

    public boolean coordsEqual(PositionProperties props) {
      return coords.equals(props.coords);
    }

    public boolean contentsEqual(World world) {
      Block block = world.getBlock(coords.posX , coords.posY, coords.posZ);
      int meta = world.getBlockMetadata(coords.posX, coords.posY, coords.posZ);
      return block == this.block && meta == this.meta;
    }
  }
}
TOP

Related Classes of vazkii.botania.common.entity.EntityManaBurst$PositionProperties

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.