Package buildcraft.energy

Source Code of buildcraft.energy.TileEngine

/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.energy;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ICrafting;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.util.ForgeDirection;
import cofh.api.energy.IEnergyHandler;
import buildcraft.api.core.NetworkData;
import buildcraft.api.power.IPowerEmitter;
import buildcraft.api.power.IPowerReceptor;
import buildcraft.api.power.PowerHandler;
import buildcraft.api.power.PowerHandler.PowerReceiver;
import buildcraft.api.transport.IPipeConnection;
import buildcraft.api.transport.IPipeTile;
import buildcraft.api.transport.IPipeTile.PipeType;
import buildcraft.core.DefaultProps;
import buildcraft.core.TileBuffer;
import buildcraft.core.TileBuildCraft;
import buildcraft.energy.gui.ContainerEngine;

public abstract class TileEngine extends TileBuildCraft implements IPowerEmitter,
    IPipeConnection, IEnergyHandler {
  // Index corresponds to metadata
  public static final ResourceLocation[] BASE_TEXTURES = new ResourceLocation[]{
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/base_wood.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/base_stone.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/base_iron.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/base_creative.png")
  };

  public static final ResourceLocation[] CHAMBER_TEXTURES = new ResourceLocation[]{
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/chamber_wood.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/chamber_stone.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/chamber_iron.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/chamber_creative.png")
  };

  // THESE ARE ONLY BLUE TRUNKS. OTHER HEAT STAGES ARE HANDLED PER TILE
  public static final ResourceLocation[] TRUNK_TEXTURES = new ResourceLocation[]{
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_wood.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_stone.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_iron.png"),
      new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_creative.png")
  };

  // TEMP
  public static final ResourceLocation TRUNK_BLUE_TEXTURE = new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_blue.png");
  public static final ResourceLocation TRUNK_GREEN_TEXTURE = new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_green.png");
  public static final ResourceLocation TRUNK_YELLOW_TEXTURE = new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_yellow.png");
  public static final ResourceLocation TRUNK_RED_TEXTURE = new ResourceLocation(DefaultProps.TEXTURE_PATH_BLOCKS + "/trunk_red.png");

  public enum EnergyStage {
    BLUE, GREEN, YELLOW, RED, OVERHEAT;
    public static final EnergyStage[] VALUES = values();
  }

  public static final float MIN_HEAT = 20;
  public static final float IDEAL_HEAT = 100;
  public static final float MAX_HEAT = 250;
  public int currentOutput = 0;
  public boolean isRedstonePowered = false;
  public float progress;
  public int energy;
  public float heat = MIN_HEAT;
  @NetworkData
  public EnergyStage energyStage = EnergyStage.BLUE;
  @NetworkData
  public ForgeDirection orientation = ForgeDirection.UP;

  protected int progressPart = 0;
  protected boolean lastPower = false;

  private boolean checkOrientation = false;
  private TileBuffer[] tileCache;

  @NetworkData
  private boolean isPumping = false; // Used for SMP synch

  public TileEngine() {
  }

  @Override
  public void initialize() {
    if (!worldObj.isRemote) {
      checkRedstonePower();
    }
  }

  public abstract ResourceLocation getBaseTexture();

  public abstract ResourceLocation getChamberTexture();

  public ResourceLocation getTrunkTexture(EnergyStage stage) {
    switch (stage) {
      case BLUE:
        return TRUNK_BLUE_TEXTURE;
      case GREEN:
        return TRUNK_GREEN_TEXTURE;
      case YELLOW:
        return TRUNK_YELLOW_TEXTURE;
      case RED:
        return TRUNK_RED_TEXTURE;
      default:
        return TRUNK_RED_TEXTURE;
    }
  }

  public boolean onBlockActivated(EntityPlayer player, ForgeDirection side) {
    return false;
  }

  public double getEnergyLevel() {
    return ((double) energy) / getMaxEnergy();
  }

  protected EnergyStage computeEnergyStage() {
    float energyLevel = getHeatLevel();
    if (energyLevel < 0.25f) {
      return EnergyStage.BLUE;
    } else if (energyLevel < 0.5f) {
      return EnergyStage.GREEN;
    } else if (energyLevel < 0.75f) {
      return EnergyStage.YELLOW;
    } else if (energyLevel < 1f) {
      return EnergyStage.RED;
    } else {
      return EnergyStage.OVERHEAT;
    }
  }

  public final EnergyStage getEnergyStage() {
    if (!worldObj.isRemote) {
      if (energyStage == EnergyStage.OVERHEAT) {
        return energyStage;
      }

      EnergyStage newStage = computeEnergyStage();

      if (energyStage != newStage) {
        energyStage = newStage;
        sendNetworkUpdate();
      }
    }

    return energyStage;
  }

  public void updateHeatLevel() {
    heat = (float) ((MAX_HEAT - MIN_HEAT) * getEnergyLevel()) + MIN_HEAT;
  }

  public float getHeatLevel() {
    return (heat - MIN_HEAT) / (MAX_HEAT - MIN_HEAT);
  }

  public float getIdealHeatLevel() {
    return heat / IDEAL_HEAT;
  }

  public float getHeat() {
    return heat;
  }

  public float getPistonSpeed() {
    if (!worldObj.isRemote) {
      return Math.max(0.16f * getHeatLevel(), 0.01f);
    }

    switch (getEnergyStage()) {
      case BLUE:
        return 0.02F;
      case GREEN:
        return 0.04F;
      case YELLOW:
        return 0.08F;
      case RED:
        return 0.16F;
      default:
        return 0;
    }
  }

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

    if (worldObj.isRemote) {
      if (progressPart != 0) {
        progress += getPistonSpeed();

        if (progress > 1) {
          progressPart = 0;
          progress = 0;
        }
      } else if (this.isPumping) {
        progressPart = 1;
      }

      return;
    }

    if (checkOrientation) {
      checkOrientation = false;

      if (!isOrientationValid()) {
        switchOrientation(true);
      } else {
        TileEntity tile = getTileBuffer(orientation).getTile();
      }
    }

    updateHeatLevel();
    getEnergyStage();
    engineUpdate();

    TileEntity tile = getTileBuffer(orientation).getTile();

    if (progressPart != 0) {
      progress += getPistonSpeed();

      if (progress > 0.5 && progressPart == 1) {
        progressPart = 2;
      } else if (progress >= 1) {
        progress = 0;
        progressPart = 0;
      }
    } else if (isRedstonePowered && isActive()) {
      if (isPoweredTile(tile, orientation)) {
        progressPart = 1;
        setPumping(true);
        if (getPowerToExtract() > 0) {
          progressPart = 1;
          setPumping(true);
        } else {
          setPumping(false);
        }
      } else {
        setPumping(false);
      }
    } else {
      setPumping(false);
    }

    burn();
   
    if (!isRedstonePowered) {
      currentOutput = 0;
    } else if (isRedstonePowered && isActive()) {
      sendPower();
    }
  }

  private int getPowerToExtract() {
    TileEntity tile = getTileBuffer(orientation).getTile();

    if (tile instanceof IEnergyHandler) {
      IEnergyHandler handler = (IEnergyHandler) tile;

      int minEnergy = 0;
      int maxEnergy = handler.receiveEnergy(
          orientation.getOpposite(),
          Math.round(this.energy), true);
      return extractEnergy(minEnergy, maxEnergy, false);
    } else if (tile instanceof IPowerReceptor) {
      PowerReceiver receptor = ((IPowerReceptor) tile)
          .getPowerReceiver(orientation.getOpposite());

      return extractEnergy((int) Math.floor(receptor.getMinEnergyReceived() * 10),
          (int) Math.ceil(receptor.getMaxEnergyReceived() * 10), false);
    } else {
      return 0;
    }
  }

  protected void sendPower() {
    TileEntity tile = getTileBuffer(orientation).getTile();
    if (isPoweredTile(tile, orientation)) {
      int extracted = getPowerToExtract();
      if (extracted > 0) {
        setPumping(true);
      } else {
        setPumping(false);
      }

      if (tile instanceof IEnergyHandler) {
        IEnergyHandler handler = (IEnergyHandler) tile;
        if (extracted > 0) {
          int neededRF = handler.receiveEnergy(
              orientation.getOpposite(),
              (int) Math.round(extracted), false);

          extractEnergy(0, neededRF, true);
        }
      } else if (tile instanceof IPowerReceptor) {
        PowerReceiver receptor = ((IPowerReceptor) tile)
            .getPowerReceiver(orientation.getOpposite());

        if (extracted > 0) {
          double neededMJ = receptor.receiveEnergy(
              PowerHandler.Type.ENGINE, extracted / 10.0,
              orientation.getOpposite());

          extractEnergy((int) Math.floor(receptor.getMinEnergyReceived() * 10), (int) Math.ceil(neededMJ * 10), true);
        }
      }
    }
  }

  // Uncomment out for constant power
//  public float getActualOutput() {
//    float heatLevel = getIdealHeatLevel();
//    return getCurrentOutput() * heatLevel;
//  }
  protected void burn() {
  }

  protected void engineUpdate() {
    if (!isRedstonePowered) {
      if (energy >= 10) {
        energy -= 10;
      } else if (energy < 10) {
        energy = 0;
      }
    }
  }

  public boolean isActive() {
    return true;
  }

  protected final void setPumping(boolean isActive) {
    if (this.isPumping == isActive) {
      return;
    }

    this.isPumping = isActive;
    sendNetworkUpdate();
  }

  public boolean isOrientationValid() {
    TileEntity tile = getTileBuffer(orientation).getTile();

    return isPoweredTile(tile, orientation);
  }

  public boolean switchOrientation(boolean preferPipe) {
    if (preferPipe && switchOrientationDo(true)) {
      return true;
    } else {
      return switchOrientationDo(false);
    }
  }

  private boolean switchOrientationDo(boolean pipesOnly) {
    for (int i = orientation.ordinal() + 1; i <= orientation.ordinal() + 6; ++i) {
      ForgeDirection o = ForgeDirection.VALID_DIRECTIONS[i % 6];

      TileEntity tile = getTileBuffer(o).getTile();

      if ((!pipesOnly || tile instanceof IPipeTile) && isPoweredTile(tile, o)) {
        orientation = o;
        worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
        worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, worldObj.getBlock(xCoord, yCoord, zCoord));

        return true;
      }
    }

    return false;
  }

  public TileBuffer getTileBuffer(ForgeDirection side) {
    if (tileCache == null) {
      tileCache = TileBuffer.makeBuffer(worldObj, xCoord, yCoord, zCoord, false);
    }

    return tileCache[side.ordinal()];
  }

  @Override
  public void invalidate() {
    super.invalidate();
    tileCache = null;
    checkOrientation = true;
  }

  @Override
  public void validate() {
    super.validate();
    tileCache = null;
    checkOrientation = true;
  }

  @Override
  public void readFromNBT(NBTTagCompound data) {
    super.readFromNBT(data);

    orientation = ForgeDirection.getOrientation(data.getByte("orientation"));
    progress = data.getFloat("progress");
    energy = data.getInteger("energy");
    heat = data.getFloat("heat");
  }

  @Override
  public void writeToNBT(NBTTagCompound data) {
    super.writeToNBT(data);

    data.setByte("orientation", (byte) orientation.ordinal());
    data.setFloat("progress", progress);
    data.setInteger("energy", energy);
    data.setFloat("heat", heat);
  }

  public void getGUINetworkData(int id, int value) {
    switch (id) {
      case 0:
        int iEnergy = Math.round(energy);
        iEnergy = (iEnergy & 0xffff0000) | (value & 0xffff);
        energy = iEnergy;
        break;
      case 1:
        iEnergy = Math.round(energy);
        iEnergy = (iEnergy & 0xffff) | ((value & 0xffff) << 16);
        energy = iEnergy;
        break;
      case 2:
        currentOutput = value;
        break;
      case 3:
        heat = value / 100F;
        break;
    }
  }

  public void sendGUINetworkData(ContainerEngine containerEngine, ICrafting iCrafting) {
    iCrafting.sendProgressBarUpdate(containerEngine, 0, Math.round(energy) & 0xffff);
    iCrafting.sendProgressBarUpdate(containerEngine, 1, (Math.round(energy) & 0xffff0000) >> 16);
    iCrafting.sendProgressBarUpdate(containerEngine, 2, Math.round(currentOutput));
    iCrafting.sendProgressBarUpdate(containerEngine, 3, Math.round(heat * 100));
  }

  /* STATE INFORMATION */
  public abstract boolean isBurning();

  public void addEnergy(int addition) {
    energy += addition;

    if (getEnergyStage() == EnergyStage.OVERHEAT) {
      worldObj.createExplosion(null, xCoord, yCoord, zCoord, explosionRange(), true);
      worldObj.setBlockToAir(xCoord, yCoord, zCoord);
    }

    if (energy > getMaxEnergy()) {
      energy = getMaxEnergy();
    }
  }

  public int extractEnergy(int min, int energyMax, boolean doExtract) {
    int max = Math.min(energyMax, maxEnergyExtracted());
   
    if (max < min || energy < min) {
      return 0;
    }

    int extracted;

    if (energy >= max) {
      extracted = max;

      if (doExtract) {
        energy -= max;
      }
    } else {
      extracted = energy;

      if (doExtract) {
        energy = 0;
      }
    }

    return extracted;
  }

  public boolean isPoweredTile(TileEntity tile, ForgeDirection side) {
    if (tile == null) {
      return false;
    } else if (tile instanceof IEnergyHandler) {
      return ((IEnergyHandler) tile).canConnectEnergy(side.getOpposite());
    } else if (tile instanceof IPowerReceptor) {
      return ((IPowerReceptor) tile).getPowerReceiver(side.getOpposite()) != null;
    } else {
      return false;
    }
  }

  public abstract int getMaxEnergy();

  public int minEnergyReceived() {
    return 20;
  }

  public abstract int maxEnergyReceived();

  public abstract int maxEnergyExtracted();

  public abstract float explosionRange();

  public int getEnergyStored() {
    return energy;
  }

  public abstract int calculateCurrentOutput();

  @Override
  public ConnectOverride overridePipeConnection(PipeType type, ForgeDirection with) {
    if (type == PipeType.POWER) {
      return ConnectOverride.DEFAULT;
    } else if (with == orientation) {
      return ConnectOverride.DISCONNECT;
    } else {
      return ConnectOverride.DEFAULT;
    }
  }

  @Override
  public boolean canEmitPowerFrom(ForgeDirection side) {
    return side == orientation;
  }

  public void checkRedstonePower() {
    isRedstonePowered = worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord);
  }

  public void onNeighborUpdate() {
    checkRedstonePower();
    checkOrientation = true;
    tileCache = null;
  }
  // RF support

  @Override
  public int receiveEnergy(ForgeDirection from, int maxReceive,
      boolean simulate) {
    return 0;
  }

  @Override
  public int extractEnergy(ForgeDirection from, int maxExtract,
      boolean simulate) {
    return 0;
  }

  @Override
  public int getEnergyStored(ForgeDirection from) {
    if (!(from == orientation)) {
      return 0;
    }

    return energy;
  }

  @Override
  public int getMaxEnergyStored(ForgeDirection from) {
    return this.getMaxEnergy();
  }

  @Override
  public boolean canConnectEnergy(ForgeDirection from) {
    return from == orientation;
  }
}
TOP

Related Classes of buildcraft.energy.TileEngine

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.