package micdoodle8.mods.galacticraft.planets.asteroids.tile; import com.google.common.collect.Lists; import micdoodle8.mods.galacticraft.api.power.EnergySource; import micdoodle8.mods.galacticraft.api.power.EnergySource.EnergySourceAdjacent; import micdoodle8.mods.galacticraft.api.power.EnergySource.EnergySourceWireless; import micdoodle8.mods.galacticraft.api.power.IEnergyHandlerGC; import micdoodle8.mods.galacticraft.api.power.ILaserNode; import micdoodle8.mods.galacticraft.api.transmission.tile.IConductor; import micdoodle8.mods.galacticraft.api.vector.BlockVec3; import micdoodle8.mods.galacticraft.api.vector.Vector3; import micdoodle8.mods.galacticraft.core.Constants; import micdoodle8.mods.galacticraft.core.energy.EnergyUtil; import micdoodle8.mods.galacticraft.core.energy.tile.*; import micdoodle8.mods.galacticraft.core.tile.ReceiverMode; import micdoodle8.mods.miccore.Annotations.NetworkedField; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class TileEntityBeamReceiver extends TileEntityBeamOutput implements IEnergyHandlerGC, ILaserNode { @NetworkedField(targetSide = Side.CLIENT) public EnumFacing facing = null; private int preLoadFacing = -1; private float maxRate = 1500; private EnergyStorage storage = new EnergyStorage(10 * maxRate, maxRate); //In broken circuits, Beam Receiver will accept energy for 0.5s (15000gJ max) then stop @NetworkedField(targetSide = Side.CLIENT) public int modeReceive = ReceiverMode.UNDEFINED.ordinal(); public Vector3 color = new Vector3(0, 1, 0); @Override public void update() { super.update(); if (this.preLoadFacing != -1) { this.setFacing(EnumFacing.getFront(this.preLoadFacing)); this.preLoadFacing = -1; } if (!this.worldObj.isRemote) { if (this.getTarget() != null && this.modeReceive == ReceiverMode.EXTRACT.ordinal() && this.facing != null) { TileEntity tile = this.getAttachedTile(); if (tile instanceof TileBaseUniversalElectricalSource) { //GC energy source TileBaseUniversalElectricalSource electricalTile = (TileBaseUniversalElectricalSource) tile; if (electricalTile.storage.getEnergyStoredGC() > 0) { EnergySourceAdjacent source = new EnergySourceAdjacent(EnumFacing.getFront(this.facing.getIndex() ^ 1)); float toSend = Math.min(electricalTile.storage.getMaxExtract(), electricalTile.storage.getEnergyStoredGC()); float transmitted = this.getTarget().receiveEnergyGC(new EnergySourceWireless(Lists.newArrayList((ILaserNode) this)), toSend, false); electricalTile.extractEnergyGC(source, transmitted, false); } } else if (!(tile instanceof EnergyStorageTile) && !(tile instanceof TileBaseConductor)) //Another mod's energy source //But don't use other mods methods to connect Beam Receivers to GC's own wires or machines { float availableToSend = EnergyUtil.otherModsEnergyExtract(tile, this.facing, this.maxRate, true); if (availableToSend > 0F) { float transmitted = this.getTarget().receiveEnergyGC(new EnergySourceWireless(Lists.newArrayList((ILaserNode) this)), availableToSend, false); EnergyUtil.otherModsEnergyExtract(tile, this.facing, transmitted, false); } } } if (this.modeReceive == ReceiverMode.RECEIVE.ordinal() && this.storage.getEnergyStoredGC() > 0) { //One Beam Receiver might be powered by multiple transmitters - allow for 5 at maximum transfer rate float maxTransfer = Math.min(this.storage.getEnergyStoredGC(), maxRate * 5); if (maxTransfer < 0.01F) //Stop updating this when de minimis energy remains { this.storage.extractEnergyGCnoMax(maxTransfer, false); } else { TileEntity tileAdj = this.getAttachedTile(); if (tileAdj instanceof TileBaseUniversalElectrical) { TileBaseUniversalElectrical electricalTile = (TileBaseUniversalElectrical) tileAdj; EnergySourceAdjacent source = new EnergySourceAdjacent(this.facing.getOpposite()); this.storage.extractEnergyGCnoMax(electricalTile.receiveEnergyGC(source, maxTransfer, false), false); } else if (!(tileAdj instanceof EnergyStorageTile) && !(tileAdj instanceof TileBaseConductor)) //Dont use other mods methods to connect Beam Receivers to GC's own wires or machines { float otherModTransferred = EnergyUtil.otherModsEnergyTransfer(tileAdj, this.facing, maxTransfer, false); if (otherModTransferred > 0F) { this.storage.extractEnergyGCnoMax(otherModTransferred, false); } } } } } } @Override public double getPacketRange() { return 24.0D; } @Override public int getPacketCooldown() { return 3; } @Override public boolean isNetworkedTile() { return true; } @Override public Vector3 getInputPoint() { Vector3 headVec = new Vector3(this.getPos().getX() + 0.5, this.getPos().getY() + 0.5, this.getPos().getZ() + 0.5); if (this.facing != null) { headVec.x += this.facing.getFrontOffsetX() * 0.1F; headVec.y += this.facing.getFrontOffsetY() * 0.1F; headVec.z += this.facing.getFrontOffsetZ() * 0.1F; } return headVec; } @Override public Vector3 getOutputPoint(boolean offset) { Vector3 headVec = new Vector3(this.getPos().getX() + 0.5, this.getPos().getY() + 0.5, this.getPos().getZ() + 0.5); if (this.facing != null) { headVec.x += this.facing.getFrontOffsetX() * 0.1F; headVec.y += this.facing.getFrontOffsetY() * 0.1F; headVec.z += this.facing.getFrontOffsetZ() * 0.1F; } return headVec; } @Override public TileEntity getTile() { return this; } public TileEntity getAttachedTile() { if (this.facing == null) { return null; } TileEntity tile = new BlockVec3(this).getTileEntityOnSide(this.worldObj, this.facing); if (tile == null || tile.isInvalid()) { this.setFacing(null); } if (tile instanceof IConductor) { this.setFacing(null /* TODO */); return null; } if (tile instanceof EnergyStorageTile) { EnergyStorage attachedStorage = ((EnergyStorageTile) tile).storage; this.storage.setCapacity(attachedStorage.getCapacityGC() - attachedStorage.getEnergyStoredGC()); this.storage.setMaxExtract(attachedStorage.getMaxExtract()); this.storage.setMaxReceive(attachedStorage.getMaxReceive()); } return tile; } @Override public float receiveEnergyGC(EnergySource from, float amount, boolean simulate) { if (this.modeReceive != ReceiverMode.RECEIVE.ordinal()) { return 0; } //TileEntity tile = this.getAttachedTile(); if (this.facing == null) { return 0; } // if (received < amount) // { // if (tile instanceof EnergyStorageTile) // { // received += ((EnergyStorageTile) tile).storage.receiveEnergyGC(amount - received, simulate); // } // } return this.storage.receiveEnergyGC(amount, simulate); } @Override public float extractEnergyGC(EnergySource from, float amount, boolean simulate) { if (this.modeReceive != ReceiverMode.EXTRACT.ordinal()) { return 0; } TileEntity tile = this.getAttachedTile(); if (this.facing == null) { return 0; } float extracted = this.storage.extractEnergyGC(amount, simulate); if (extracted < amount) { if (tile instanceof EnergyStorageTile) { extracted += ((EnergyStorageTile) tile).storage.extractEnergyGC(amount - extracted, simulate); } } return extracted; } @Override public float getEnergyStoredGC(EnergySource from) { TileEntity tile = this.getAttachedTile(); if (this.facing == null) { return 0; } return this.storage.getEnergyStoredGC(); } @Override public float getMaxEnergyStoredGC(EnergySource from) { TileEntity tile = this.getAttachedTile(); if (this.facing == null) { return 0; } return this.storage.getCapacityGC(); } @Override public boolean nodeAvailable(EnergySource from) { TileEntity tile = this.getAttachedTile(); return this.facing != null; } public void setFacing(EnumFacing newDirection) { if (newDirection != this.facing) { if (newDirection == null) { this.modeReceive = ReceiverMode.UNDEFINED.ordinal(); } else { TileEntity tile = new BlockVec3(this).getTileEntityOnSide(this.worldObj, newDirection); if (tile == null) { this.modeReceive = ReceiverMode.UNDEFINED.ordinal(); } else if (tile instanceof EnergyStorageTile) { ReceiverMode mode = ((EnergyStorageTile) tile).getModeFromDirection(newDirection.getOpposite()); if (mode != null) { this.modeReceive = mode.ordinal(); } else { this.modeReceive = ReceiverMode.UNDEFINED.ordinal(); } } else if (EnergyUtil.otherModCanReceive(tile, newDirection.getOpposite())) { this.modeReceive = ReceiverMode.RECEIVE.ordinal(); } else if (EnergyUtil.otherModCanProduce(tile, newDirection.getOpposite())) { this.modeReceive = ReceiverMode.EXTRACT.ordinal(); } } } this.facing = newDirection; } @Override public boolean canConnectTo(ILaserNode laserNode) { if (this.modeReceive != ReceiverMode.UNDEFINED.ordinal() && this.color.equals(laserNode.getColor())) { if (laserNode instanceof TileEntityBeamReceiver) { return ((TileEntityBeamReceiver) laserNode).modeReceive != this.modeReceive; } return true; } return false; } @Override public Vector3 getColor() { return new Vector3(0, 1, 0); } @Override public ILaserNode getTarget() { if (this.modeReceive == ReceiverMode.EXTRACT.ordinal()) { return super.getTarget(); } return null; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); this.preLoadFacing = nbt.getInteger("FacingSide"); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setInteger("FacingSide", this.facing.ordinal()); } private AxisAlignedBB renderAABB; @Override @SideOnly(Side.CLIENT) public AxisAlignedBB getRenderBoundingBox() { if (this.renderAABB == null) { this.renderAABB = new AxisAlignedBB(pos, pos.add(1, 2, 1)); } return this.renderAABB; } @Override @SideOnly(Side.CLIENT) public double getMaxRenderDistanceSquared() { return Constants.RENDERDISTANCE_SHORT; } }