Package erogenousbeef.bigreactors.common.multiblock.tileentity

Source Code of erogenousbeef.bigreactors.common.multiblock.tileentity.TileEntityReactorRedstonePort

package erogenousbeef.bigreactors.common.multiblock.tileentity;

import net.minecraft.block.Block;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import erogenousbeef.bigreactors.client.gui.GuiReactorRedstonePort;
import erogenousbeef.bigreactors.common.BigReactors;
import erogenousbeef.bigreactors.common.multiblock.MultiblockReactor;
import erogenousbeef.bigreactors.common.multiblock.block.BlockReactorRedstonePort;
import erogenousbeef.bigreactors.common.multiblock.interfaces.ITickableMultiblockPart;
import erogenousbeef.bigreactors.common.multiblock.tileentity.TileEntityReactorRedNetPort.CircuitType;
import erogenousbeef.bigreactors.gui.container.ContainerBasic;
import erogenousbeef.core.multiblock.MultiblockControllerBase;
import erogenousbeef.core.multiblock.MultiblockValidationException;

public class TileEntityReactorRedstonePort extends TileEntityReactorPartBase
    implements ITickableMultiblockPart {

  protected CircuitType circuitType;
  protected int outputLevel;
  protected boolean activeOnPulse;
  protected boolean greaterThan; // if false, less than
 
  protected int ticksSinceLastUpdate;
 
  // These are local-only and used for handy state calculations
  protected boolean isExternallyPowered;
 
  public TileEntityReactorRedstonePort() {
    super();
   
    circuitType = circuitType.DISABLED;
    isExternallyPowered = false;
    ticksSinceLastUpdate = 0;
  }
 
  // Redstone methods
  public boolean isRedstoneActive() {
    if(!this.isConnected()) { return false; }

    MultiblockReactor reactor = (MultiblockReactor)getMultiblockController();

    switch(circuitType) {
    case outputFuelTemperature:
      return checkVariable((int)reactor.getFuelHeat());
    case outputCasingTemperature:
      return checkVariable((int)reactor.getReactorHeat());
    case outputFuelMix:
      return checkVariable((int)(reactor.getFuelRichness()*100));
    case outputFuelAmount:
      return checkVariable(reactor.getFuelAmount());
    case outputWasteAmount:
      return checkVariable(reactor.getWasteAmount());
    case outputEnergyAmount:
      return checkVariable(reactor.getEnergyStoredPercentage());
    case DISABLED:
      return false;
    default:
      return this.isExternallyPowered;
    }
  }
 
  public boolean isInput() {
    return TileEntityReactorRedNetPort.isInput(this.circuitType);
  }
 
  public boolean isOutput() {
    return TileEntityReactorRedNetPort.isOutput(this.circuitType);
  }
 
  protected boolean checkVariable(int value) {
    if(this.greaterThan) {
      return value > getOutputLevel();
    }
    else {
      return value < getOutputLevel();
    }
  }
 
  public void sendRedstoneUpdate() {
    if(this.worldObj != null && !this.worldObj.isRemote) {
      int md;

      if(this.isOutput()) {
        md = isRedstoneActive() ? BlockReactorRedstonePort.META_REDSTONE_LIT : BlockReactorRedstonePort.META_REDSTONE_UNLIT;
      }
      else {
        md = isExternallyPowered ? BlockReactorRedstonePort.META_REDSTONE_LIT : BlockReactorRedstonePort.META_REDSTONE_UNLIT;
      }

      if(md != this.worldObj.getBlockMetadata(xCoord, yCoord, zCoord)) {
        this.worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, md, 3);
      }
    }
  }
 
  public void onNeighborBlockChange(int x, int y, int z, Block neighborBlock) {
    if(!this.isConnected()) { return; }

    if(this.isInput()) {
      ForgeDirection out = getOutwardsDir();
      boolean nowPowered = isReceivingRedstonePowerFrom(worldObj, xCoord+out.offsetX, yCoord+out.offsetY, zCoord+out.offsetZ, out, neighborBlock);

      if(this.isExternallyPowered != nowPowered) {
        this.isExternallyPowered = nowPowered;
        this.onRedstoneInputUpdated();
        this.sendRedstoneUpdate();
      }
    }
    else {
      this.isExternallyPowered = false;
    }
  }

  // Called to do business logic when the redstone value has changed
  protected void onRedstoneInputUpdated() {
    if(!this.isConnected()) { return; }

    MultiblockReactor reactor = (MultiblockReactor)getMultiblockController();
    switch(this.circuitType) {
    case inputActive:
      if(this.isInputActiveOnPulse()) {
        if(this.isExternallyPowered) {
          reactor.setActive(!reactor.getActive());
        }
      }
      else {
        reactor.setActive(this.isExternallyPowered);
      }
      break;
    case inputSetControlRod:
      // On/off only
      if(this.isInputActiveOnPulse()) {
        if(this.isExternallyPowered) {
          if(this.shouldSetControlRodsInsteadOfChange()) {
            reactor.setAllControlRodInsertionValues(this.outputLevel);
          }
          else {
            reactor.changeAllControlRodInsertionValues((short)this.outputLevel); // Can be negative, don't want to mask.
          }
        }
      }
      else {
        if(this.isExternallyPowered) {
          reactor.setAllControlRodInsertionValues(getControlRodLevelWhileOn());
        }
        else {
          reactor.setAllControlRodInsertionValues(getControlRodLevelWhileOff());
        }
      }
      break;
    case inputEjectWaste:
      // Pulse only
      if(this.isExternallyPowered) {
        reactor.ejectWaste(false, null);
      }
      break;
    default:
      break;
    }
  }
 
  public int getOutputLevel() { return outputLevel; }
  public int getControlRodLevelWhileOff() { return ((outputLevel & 0xFF00) >> 8) & 0xFF; }
  public int getControlRodLevelWhileOn () { return outputLevel & 0xFF; }
 
  public static int packControlRodLevels(byte off, byte on) {
    return (((int)off << 8) & 0xFF00) | (on & 0xFF);
  }

  public static int unpackControlRodLevelOn(int level) {
    return level & 0xFF;
  }
 
  public static int unpackControlRodLevelOff(int level) {
    return ((level % 0xFF00) >> 8) & 0xFF;
  }

  public boolean isInputActiveOnPulse() {
    return this.activeOnPulse;
  }

  /**
   * @param newType The type of the new circuit.
   * @param param1 For input/control rods, the level(s) to change or set. For outputs, the numerical value
   * @param greaterThan For outputs, whether to activate when greater than or less than the outputLevel value. For input/control rods, whether to set (true) or change (false) the values.
   */
  public void onReceiveUpdatePacket(int newType, int outputLevel, boolean greaterThan, boolean activeOnPulse) {
    this.circuitType = CircuitType.values()[newType];
    this.outputLevel = outputLevel;
    this.greaterThan = greaterThan;
    this.activeOnPulse = activeOnPulse;

    if(isAlwaysActiveOnPulse(circuitType)) { this.activeOnPulse = true; }
    else if(TileEntityReactorRedNetPort.isOutput(this.circuitType)) { this.activeOnPulse = false; }
   
    // Do updates
    if(this.isInput()) {
      // Update inputs so we don't pulse/change automatically
      ForgeDirection out = getOutwardsDir();
      this.isExternallyPowered = isReceivingRedstonePowerFrom(worldObj, xCoord+out.offsetX, yCoord+out.offsetY, zCoord+out.offsetZ, out);
      if(!this.isInputActiveOnPulse()) {
        onRedstoneInputUpdated();
      }
    }
    else {
      this.isExternallyPowered = false;
    }

    // Ensure visuals and metadata reflect our new settings & state
    this.sendRedstoneUpdate();

    if(!this.worldObj.isRemote) {
      // Propagate the new settings
      this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
      this.worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this);
    }
  }
 
  @SideOnly(Side.CLIENT)
  public boolean getGreaterThan() { return this.greaterThan; }
 
  public CircuitType getCircuitType() { return this.circuitType; }
  private boolean shouldSetControlRodsInsteadOfChange() { return !greaterThan; }

  public void onRedNetUpdate(int powerLevel) {
    if(this.isInput()) {
      boolean wasPowered = this.isExternallyPowered;
      this.isExternallyPowered = powerLevel > 0;
      if(wasPowered != this.isExternallyPowered) {
        this.onRedstoneInputUpdated();
        this.sendRedstoneUpdate();
      }
    }
  }
 
  /**
   * Call with the coordinates of the block to check and the direction
   * towards that block from your block.
   * If the block towards which this block is emitting power lies north,
   * then pass in south.
   */
  private boolean isReceivingRedstonePowerFrom(World world, int x, int y, int z, ForgeDirection dir) {
    // This is because of bugs in vanilla redstone wires
    Block block = world.getBlock(x, y, z);
    return isReceivingRedstonePowerFrom(world, x, y, z, dir, block);
  }
 
  /**
   * Call with the coordinates of the block to check and the direction
   * towards that block from your block.
   * If the block towards which this block is emitting power lies north,
   * then pass in south.
   */
  private boolean isReceivingRedstonePowerFrom(World world, int x, int y, int z, ForgeDirection dir, Block neighborBlock) {
    if(neighborBlock == Blocks.redstone_wire) {
      // Use metadata because of vanilla redstone wire bugs
      return world.getBlockMetadata(x, y, z) > 0;
    }
    else {
      return world.getIndirectPowerOutput(x, y, z, dir.ordinal()) || world.isBlockProvidingPowerTo(x, y, z, dir.ordinal()) > 0;
    }
  }
 
  // TileEntity overrides

  // Only refresh if we're switching functionality
  // Warning: dragonz!
  @Override
    public boolean shouldRefresh(Block oldID, Block newID, int oldMeta, int newMeta, World world, int x, int y, int z)
    {
    if(oldID != newID) {
      return true;
    }
 
    // All redstone ports are the same, we just use metadata to easily signal changes.
    return false;
    }

  // IReactorTickable
  /**
   * Updates the redstone block's status, if it's an output network, if there is one.
   * Will only send one update per N ticks, where N is a configurable setting.
   */
  public void onMultiblockServerTick() {
    if(!this.isConnected()) { return; }

    ticksSinceLastUpdate++;
    if(ticksSinceLastUpdate < BigReactors.ticksPerRedstoneUpdate) { return; }

    if(this.isOutput()) {
      // Will no-op if there's no change.
      this.sendRedstoneUpdate();
    }
    ticksSinceLastUpdate = 0;
  }
 
  // MultiblockTileEntityBase methods
  private void readData(NBTTagCompound data) {
    if(data.hasKey("circuitType")) {
      this.circuitType = circuitType.values()[data.getInteger("circuitType")];
    }
   
    if(data.hasKey("outputLevel")) {
      this.outputLevel = data.getInteger("outputLevel");
    }
   
    if(data.hasKey("greaterThan")) {
      this.greaterThan = data.getBoolean("greaterThan");
    }
   
    if(data.hasKey("activeOnPulse")) {
      this.activeOnPulse = data.getBoolean("activeOnPulse");
    }
  }
 
  private void writeData(NBTTagCompound data) {
    data.setInteger("circuitType", this.circuitType.ordinal());
    data.setInteger("outputLevel", this.outputLevel);
    data.setBoolean("greaterThan", this.greaterThan);
    data.setBoolean("activeOnPulse", this.activeOnPulse);
  }

  @Override
  public void readFromNBT(NBTTagCompound data) {
    super.readFromNBT(data);
    this.readData(data);
    this.sendRedstoneUpdate();
  }

  @Override
  public void writeToNBT(NBTTagCompound data) {
    super.writeToNBT(data);
    this.writeData(data);
  }
 
  @Override
  public void decodeDescriptionPacket(NBTTagCompound data) {
    super.decodeDescriptionPacket(data);
    this.readData(data);
  }

  @Override
  public void encodeDescriptionPacket(NBTTagCompound data) {
    super.encodeDescriptionPacket(data);
    this.writeData(data);
  }
 
  @Override
  public void isGoodForFrame() throws MultiblockValidationException {
    throw new MultiblockValidationException(String.format("%d, %d, %d - Redstone ports may only be placed on a reactor's external side faces, not as part of the frame", xCoord, yCoord, zCoord));
  }

  @Override
  public void isGoodForSides() throws MultiblockValidationException {
  }

  @Override
  public void isGoodForTop() throws MultiblockValidationException {
    throw new MultiblockValidationException(String.format("%d, %d, %d - Redstone ports may only be placed on a reactor's external side faces, not the top", xCoord, yCoord, zCoord));
  }

  @Override
  public void isGoodForBottom() throws MultiblockValidationException {
    throw new MultiblockValidationException(String.format("%d, %d, %d - Redstone ports may only be placed on a reactor's external side faces, not the bottom", xCoord, yCoord, zCoord));
  }

  @Override
  public void isGoodForInterior() throws MultiblockValidationException {
    throw new MultiblockValidationException(String.format("%d, %d, %d - Redstone ports may not be placed in a reactor's interior", xCoord, yCoord, zCoord));
  }

  @Override
  public void onMachineAssembled(MultiblockControllerBase controller) {
    super.onMachineAssembled(controller);
    this.sendRedstoneUpdate();
  }

  @Override
  public void onMachineBroken() {
    super.onMachineBroken();
    this.sendRedstoneUpdate();
  }

  @Override
  public void onMachineActivated() {
    this.sendRedstoneUpdate();
  }

  @Override
  public void onMachineDeactivated() {
    this.sendRedstoneUpdate();
  }

  // IBeefGuiEntity
  @SideOnly(Side.CLIENT)
  @Override
  public Object getGuiElement(InventoryPlayer inventoryPlayer) {
    return new GuiReactorRedstonePort(new ContainerBasic(), this);
  }

  @Override
  public Object getContainer(InventoryPlayer inventoryPlayer) {
    return new ContainerBasic();
  }

  public static boolean isAlwaysActiveOnPulse(CircuitType circuitType) {
    return circuitType == CircuitType.inputEjectWaste;
  }
}
TOP

Related Classes of erogenousbeef.bigreactors.common.multiblock.tileentity.TileEntityReactorRedstonePort

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.