Package mffs.tile

Source Code of mffs.tile.TileForceFieldProjector

package mffs.tile;

import calclavia.api.mffs.ICache;
import calclavia.api.mffs.IProjector;
import calclavia.api.mffs.modules.IModule;
import calclavia.api.mffs.modules.IProjectorMode;
import com.google.common.io.ByteArrayDataInput;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import mffs.ModularForceFieldSystem;
import mffs.Settings;
import mffs.card.ItemCard;
import mffs.item.mode.ItemModeCustom;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import resonant.lib.network.PacketHandler;
import universalelectricity.api.vector.Vector3;

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class TileForceFieldProjector extends TileFieldInteraction implements IProjector, IThreadCallBack
{
  /**
   * A set containing all positions of all force field blocks.
   */
  protected final Set<Vector3> forceFields = new HashSet();
  public boolean markFieldUpdate = true;
  /**
   * True if the field is done constructing and the projector is simply maintaining the field *
   */
  private boolean isCompleteConstructing = false;
  private boolean fieldRequireTicks = false;

  public TileForceFieldProjector()
  {
    this.capacityBase = 50;
    this.startModuleIndex = 1;
  }

  @Override
  public void initiate()
  {
    super.initiate();
    this.calculateForceField(this);
  }

  @Override
  public void onReceivePacket(int packetID, ByteArrayDataInput dataStream) throws IOException
  {
    super.onReceivePacket(packetID, dataStream);

    /**
     * Stabilizer Module Construction FXs
     */
    if (worldObj.isRemote)
    {
      if (packetID == TilePacketType.FXS.ordinal())
      {
        int type = dataStream.readInt();
        Vector3 vector = new Vector3(dataStream.readInt(), dataStream.readInt(), dataStream.readInt()).translate(0.5);
        Vector3 root = new Vector3(this).translate(0.5);

        if (type == 1)
        {
          ModularForceFieldSystem.proxy.renderBeam(this.worldObj, root, vector, 0.6f, 0.6f, 1, 40);
          ModularForceFieldSystem.proxy.renderHologramMoving(this.worldObj, vector, 1, 1, 1, 50);
        }
        else if (type == 2)
        {
          ModularForceFieldSystem.proxy.renderBeam(this.worldObj, vector, root, 1f, 0f, 0f, 40);
          ModularForceFieldSystem.proxy.renderHologramMoving(this.worldObj, vector, 1, 0, 0, 50);
        }
      }
      else if (packetID == TilePacketType.FIELD.ordinal())
      {
        this.getCalculatedField().clear();
        NBTTagCompound nbt = PacketHandler.readNBTTagCompound(dataStream);
        NBTTagList nbtList = nbt.getTagList("blockList");

        for (int i = 0; i < nbtList.tagCount(); i++)
        {
          NBTTagCompound tagAt = (NBTTagCompound) nbtList.tagAt(i);
          this.getCalculatedField().add(new Vector3(tagAt));
        }

        this.isCalculated = true;
      }
    }
  }

  public void sendFieldToClient()
  {
    NBTTagCompound nbt = new NBTTagCompound();
    NBTTagList nbtList = new NBTTagList();

    for (Vector3 vector : this.getCalculatedField())
    {
      nbtList.appendTag(vector.writeToNBT(new NBTTagCompound()));
    }

    nbt.setTag("blockList", nbtList);
    PacketDispatcher.sendPacketToAllPlayers(ModularForceFieldSystem.PACKET_TILE.getPacket(this, TilePacketType.FIELD.ordinal(), nbt));
  }

  @Override
  protected void calculateForceField(IThreadCallBack callBack)
  {
    if (!this.worldObj.isRemote && !this.isCalculating)
    {
      if (this.getMode() != null)
      {
        this.forceFields.clear();
      }
    }

    super.calculateForceField(callBack);
    this.isCompleteConstructing = false;
    this.fieldRequireTicks = false;

    if (this.getModuleStacks() != null)
    {
      for (ItemStack module : this.getModuleStacks())
      {
        if (module != null && ((IModule) module.getItem()).requireTicks(module))
        {
          fieldRequireTicks = true;
          break;
        }
      }
    }
  }

  @Override
  public void onThreadComplete()
  {
    // TODO: Send packet on start-up?
    if (this.clientSideSimulationRequired())
    {
      this.sendFieldToClient();
    }
  }

  private boolean clientSideSimulationRequired()
  {
    return this.getModuleCount(ModularForceFieldSystem.itemModuleRepulsion) > 0;
  }

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

    if (this.isActive() && this.getMode() != null && this.requestFortron(this.getFortronCost(), false) >= this.getFortronCost())
    {
      this.consumeCost();

      if (this.ticks % 10 == 0 || this.markFieldUpdate || this.fieldRequireTicks)
      {
        if (!this.isCalculated)
        {
          this.calculateForceField(this);
        }
        else
        {
          this.projectField();
        }
      }

      if (isActive() && worldObj.isRemote)
      {
        animation += getFortronCost() / 100f;
      }

      if (ticks % (2 * 20) == 0 && this.getModuleCount(ModularForceFieldSystem.itemModuleSilence) <= 0)
      {
        worldObj.playSoundEffect(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D, ModularForceFieldSystem.PREFIX + "field", 0.6f, (1 - this.worldObj.rand.nextFloat() * 0.1f));
      }
    }
    else if (!worldObj.isRemote)
    {
      destroyField();
    }
  }

  /**
   * Returns Fortron cost in ticks.
   */
  @Override
  protected int doGetFortronCost()
  {
    if (this.getMode() != null)
    {
      return Math.round(super.doGetFortronCost() + this.getMode().getFortronCost(this.getAmplifier()));
    }

    return 0;
  }

  @Override
  protected float getAmplifier()
  {
    if (this.getMode() instanceof ItemModeCustom)
    {
      return Math.max(((ItemModeCustom) this.getMode()).getFieldBlocks(this, this.getModeStack()).size() / 100, 1);
    }

    return Math.max(Math.min((this.getCalculatedField().size() / 1000), 10), 1);
  }

  @Override
  public void onInventoryChanged()
  {
    super.onInventoryChanged();
    this.destroyField();
  }

  /**
   * Projects a force field based on the calculations made.
   */
  @Override
  public void projectField()
  {
    if (isCalculated && !isCalculating)
    {
      if (!isCompleteConstructing || markFieldUpdate || fieldRequireTicks)
      {
        markFieldUpdate = false;

        if (forceFields.size() <= 0)
        {
          if (getModeStack().getItem() instanceof ICache)
          {
            ((ICache) getModeStack().getItem()).clearCache();
          }
        }

        int constructionCount = 0;
        int constructionSpeed = Math.min(this.getProjectionSpeed(), Settings.MAX_FORCE_FIELDS_PER_TICK);

        Set<Vector3> fieldToBeProjected = new HashSet(calculatedField);

        for (IModule module : this.getModules(this.getModuleSlots()))
        {
          if (module.onProject(this, fieldToBeProjected))
          {
            return;
          }
        }

        Iterator<Vector3> it = fieldToBeProjected.iterator();

        fieldLoop:
        while (it.hasNext())
        {
          Vector3 vector = it.next();

          Block block = Block.blocksList[vector.getBlockID(this.worldObj)];

          if (canReplaceBlock(vector, block))
          {
            /**
             * Prevents the force field projector from disintegrating itself.
             */
            if (block != ModularForceFieldSystem.blockForceField && !vector.equals(new Vector3(this)))
            {
              if (this.worldObj.getChunkFromBlockCoords(vector.intX(), vector.intZ()).isChunkLoaded)
              {
                constructionCount++;

                for (IModule module : getModules(getModuleSlots()))
                {
                  int flag = module.onProject(this, vector.clone());

                  if (flag == 1)
                  {
                    continue fieldLoop;
                  }
                  else if (flag == 2)
                  {
                    break fieldLoop;
                  }
                }

                if (!this.worldObj.isRemote)
                {
                  this.worldObj.setBlock(vector.intX(), vector.intY(), vector.intZ(), ModularForceFieldSystem.blockForceField.blockID, 0, 2);
                }

                this.forceFields.add(vector);

                  /*
                   * Sets the controlling projector of the force field block to
                   * this one.
                   */
                TileEntity tileEntity = this.worldObj.getBlockTileEntity(vector.intX(), vector.intY(), vector.intZ());

                if (tileEntity instanceof TileForceField)
                {
                  ((TileForceField) tileEntity).setProjector(new Vector3(this));
                }

                this.requestFortron(1, true);

                if (constructionCount >= constructionSpeed)
                {
                  break;
                }
              }
            }
          }
        }

        /**
         * Change the field to tick every second when construction completes.
         */
        isCompleteConstructing = constructionCount == 0;

      }
    }
  }

  private boolean canReplaceBlock(Vector3 vector, Block block)
  {
    return block == null || (this.getModuleCount(ModularForceFieldSystem.itemModuleDisintegration) > 0 && block.getBlockHardness(this.worldObj, vector.intX(), vector.intY(), vector.intZ()) != -1) || block.blockMaterial.isLiquid() || block == Block.snow || block == Block.vine || block == Block.tallGrass || block == Block.deadBush || block.isBlockReplaceable(this.worldObj, vector.intX(), vector.intY(), vector.intZ());
  }

  @Override
  public void destroyField()
  {
    if (!this.worldObj.isRemote && this.isCalculated && !this.isCalculating)
    {
      synchronized (calculatedField)
      {
        HashSet<Vector3> copiedSet = new HashSet<Vector3>(calculatedField);
        Iterator<Vector3> it = copiedSet.iterator();

        for (IModule module : this.getModules(this.getModuleSlots()))
        {
          if (module.onDestroy(this, this.getCalculatedField()))
          {
            break;
          }
        }

        while (it.hasNext())
        {
          Vector3 vector = it.next();
          Block block = Block.blocksList[vector.getBlockID(this.worldObj)];

          if (block == ModularForceFieldSystem.blockForceField)
          {
            this.worldObj.setBlock(vector.intX(), vector.intY(), vector.intZ(), 0, 0, 3);
          }
        }
      }
    }

    this.forceFields.clear();
    this.calculatedField.clear();
    this.isCalculated = false;
    this.isCompleteConstructing = false;
    this.fieldRequireTicks = false;
  }

  @Override
  public void invalidate()
  {
    this.destroyField();
    super.invalidate();
  }

  @Override
  public int getProjectionSpeed()
  {
    return 28 + 28 * this.getModuleCount(ModularForceFieldSystem.itemModuleSpeed, this.getModuleSlots());
  }

  @Override
  public int getSizeInventory()
  {
    return 3 + 18;
  }

  @Override
  public Set<Vector3> getForceFields()
  {
    return this.forceFields;
  }

  @Override
  public boolean isItemValidForSlot(int slotID, ItemStack itemStack)
  {
    if (slotID == 0 || slotID == 1)
    {
      return itemStack.getItem() instanceof ItemCard;
    }
    else if (slotID == MODULE_SLOT_ID)
    {
      return itemStack.getItem() instanceof IProjectorMode;
    }
    else if (slotID >= 15)
    {
      return true;
    }

    return itemStack.getItem() instanceof IModule;
  }

  @Override
  public Set<ItemStack> getCards()
  {
    Set<ItemStack> cards = new HashSet<ItemStack>();
    cards.add(super.getCard());
    cards.add(this.getStackInSlot(1));
    return cards;
  }

  @Override
  @SideOnly(Side.CLIENT)
  public AxisAlignedBB getRenderBoundingBox()
  {
    return AxisAlignedBB.getAABBPool().getAABB(this.xCoord, this.yCoord, this.zCoord, this.xCoord + 1, this.yCoord + 2, this.zCoord + 1);
  }

  @Override
  public long getTicks()
  {
    return this.ticks;
  }

}
TOP

Related Classes of mffs.tile.TileForceFieldProjector

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.