/** Invalidates a TileEntity */
  public static void invalidate(TileEntity tileEntity) {
    for (int i = 0; i < 6; i++) {
      ForgeDirection direction = ForgeDirection.getOrientation(i);
      TileEntity checkTile =
          VectorHelper.getConnectorFromSide(
              tileEntity.worldObj, new Vector3(tileEntity), direction);

      if (checkTile instanceof INetworkPart) {
        NetworkTileEntities network = ((INetworkPart) checkTile).getTileNetwork();

        if (network != null && network instanceof NetworkFluidTiles) {
          network.removeTile(tileEntity);
        }
      }
    }
  }
  /**
   * Invalidates a TileEntity from the electrical network, thereby removing it from all electricity
   * network that are adjacent to it.
   */
  public static void invalidate(TileEntity tileEntity) {
    for (int i = 0; i < 6; i++) {
      ForgeDirection direction = ForgeDirection.getOrientation(i);
      TileEntity checkTile =
          VectorHelper.getConnectorFromSide(
              tileEntity.worldObj, new Vector3(tileEntity), direction);

      if (checkTile instanceof INetworkProvider) {
        IElectricityNetwork network = ((INetworkProvider) checkTile).getNetwork();

        if (network != null) {
          network.stopRequesting(tileEntity);
          network.stopProducing(tileEntity);
        }
      }
    }
  }
  @Override
  public boolean produceUE(ForgeDirection outputDirection) {
    if (!this.worldObj.isRemote
        && outputDirection != null
        && outputDirection != ForgeDirection.UNKNOWN) {
      float provide = this.getProvide(outputDirection);

      if (provide > 0) {
        TileEntity outputTile =
            VectorHelper.getConnectorFromSide(this.worldObj, new Vector3(this), outputDirection);
        IElectricityNetwork outputNetwork =
            ElectricityHelper.getNetworkFromTileEntity(outputTile, outputDirection);
        if (outputNetwork != null) {
          ElectricityPack powerRequest = outputNetwork.getRequest(this);

          if (powerRequest.getWatts() > 0) {
            ElectricityPack sendPack =
                ElectricityPack.min(
                    ElectricityPack.getFromWatts(this.getEnergyStored(), this.getVoltage()),
                    ElectricityPack.getFromWatts(provide, this.getVoltage()));
            float rejectedPower = outputNetwork.produce(sendPack, this);
            this.provideElectricity(sendPack.getWatts() - rejectedPower, true);
            return true;
          }
        } else if (outputTile instanceof IElectrical) {
          float requestedEnergy =
              ((IElectrical) outputTile).getRequest(outputDirection.getOpposite());

          if (requestedEnergy > 0) {
            ElectricityPack sendPack =
                ElectricityPack.min(
                    ElectricityPack.getFromWatts(this.getEnergyStored(), this.getVoltage()),
                    ElectricityPack.getFromWatts(provide, this.getVoltage()));
            float acceptedEnergy =
                ((IElectrical) outputTile)
                    .receiveElectricity(outputDirection.getOpposite(), sendPack, true);
            this.setEnergyStored(this.getEnergyStored() - acceptedEnergy);
            return true;
          }
        }
      }
    }

    return false;
  }
  @Override
  public void onUpdate() {
    super.onUpdate();

    if (powerProvider != null) {
      int received =
          (int)
              (powerProvider.useEnergy(
                      0,
                      (float) ((tier.MAX_ELECTRICITY - electricityStored) * Mekanism.TO_BC),
                      true)
                  * Mekanism.FROM_BC);
      setJoules(electricityStored + received);
    }

    if (inventory[0] != null && electricityStored > 0) {
      setJoules(
          getJoules() - ElectricItemHelper.chargeItem(inventory[0], getJoules(), getVoltage()));

      if (Mekanism.hooks.IC2Loaded && inventory[0].getItem() instanceof IElectricItem) {
        double sent =
            ElectricItem.charge(
                    inventory[0], (int) (electricityStored * Mekanism.TO_IC2), 3, false, false)
                * Mekanism.FROM_IC2;
        setJoules(electricityStored - sent);
      }
    }

    if (inventory[1] != null && electricityStored < tier.MAX_ELECTRICITY) {
      setJoules(
          getJoules()
              + ElectricItemHelper.dechargeItem(
                  inventory[1], getMaxJoules() - getJoules(), getVoltage()));

      if (Mekanism.hooks.IC2Loaded && inventory[1].getItem() instanceof IElectricItem) {
        IElectricItem item = (IElectricItem) inventory[1].getItem();
        if (item.canProvideEnergy()) {
          double gain =
              ElectricItem.discharge(
                      inventory[1],
                      (int) ((tier.MAX_ELECTRICITY - electricityStored) * Mekanism.TO_IC2),
                      3,
                      false,
                      false)
                  * Mekanism.FROM_IC2;
          setJoules(electricityStored + gain);
        }
      } else if (inventory[1].itemID == Item.redstone.itemID
          && electricityStored + 1000 <= tier.MAX_ELECTRICITY) {
        setJoules(electricityStored + 1000);
        --inventory[1].stackSize;

        if (inventory[1].stackSize <= 0) {
          inventory[1] = null;
        }
      }
    }

    if (electricityStored > 0) {
      TileEntity tileEntity =
          VectorHelper.getTileEntityFromSide(
              worldObj, new Vector3(this), ForgeDirection.getOrientation(facing));

      if (Mekanism.hooks.IC2Loaded) {
        if (electricityStored >= output) {
          EnergyTileSourceEvent event = new EnergyTileSourceEvent(this, output);
          MinecraftForge.EVENT_BUS.post(event);
          setJoules(electricityStored - (output - event.amount));
        }
      }

      if (tileEntity != null) {
        if (isPowerReceptor(tileEntity)) {
          IPowerReceptor receptor = (IPowerReceptor) tileEntity;
          double electricityNeeded =
              Math.min(
                      receptor.powerRequest(),
                      receptor.getPowerProvider().getMaxEnergyStored()
                          - receptor.getPowerProvider().getEnergyStored())
                  * Mekanism.FROM_BC;
          float transferEnergy =
              (float) Math.min(electricityStored, Math.min(electricityNeeded, output));
          receptor
              .getPowerProvider()
              .receiveEnergy(
                  (float) (transferEnergy * Mekanism.TO_BC),
                  ForgeDirection.getOrientation(facing).getOpposite());
          setJoules(electricityStored - transferEnergy);
        }
      }
    }

    if (!worldObj.isRemote) {
      ForgeDirection outputDirection = ForgeDirection.getOrientation(facing);
      ArrayList<IElectricityNetwork> inputNetworks = new ArrayList<IElectricityNetwork>();

      for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
        if (direction != outputDirection) {
          IElectricityNetwork network =
              ElectricityNetworkHelper.getNetworkFromTileEntity(
                  VectorHelper.getTileEntityFromSide(worldObj, new Vector3(this), direction),
                  direction);
          if (network != null) {
            inputNetworks.add(network);
          }
        }
      }

      TileEntity outputTile =
          VectorHelper.getTileEntityFromSide(worldObj, new Vector3(this), outputDirection);

      IElectricityNetwork outputNetwork =
          ElectricityNetworkHelper.getNetworkFromTileEntity(outputTile, outputDirection);

      if (outputNetwork != null && !inputNetworks.contains(outputNetwork)) {
        double outputWatts =
            Math.min(outputNetwork.getRequest().getWatts(), Math.min(getJoules(), 10000));

        if (getJoules() > 0 && outputWatts > 0 && getJoules() - outputWatts >= 0) {
          outputNetwork.startProducing(
              this, Math.min(outputWatts, getJoules()) / getVoltage(), getVoltage());
          setJoules(electricityStored - outputWatts);
        } else {
          outputNetwork.stopProducing(this);
        }
      }
    }
  }