blob: 6fddbf4c4f5dd126418b5072916f9012e3a7e138 [file] [log] [blame] [raw]
package mekanism.common.tile.transmitter;
import ic2.api.energy.EnergyNet;
import ic2.api.energy.tile.IEnergySource;
import ic2.api.energy.tile.IEnergyTile;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import mekanism.api.energy.EnergyStack;
import mekanism.api.energy.IStrictEnergyAcceptor;
import mekanism.api.energy.IStrictEnergyStorage;
import mekanism.api.transmitters.TransmissionType;
import mekanism.common.Tier;
import mekanism.common.Tier.BaseTier;
import mekanism.common.Tier.CableTier;
import mekanism.common.base.EnergyAcceptorWrapper;
import mekanism.common.block.states.BlockStateTransmitter.TransmitterType;
import mekanism.common.capabilities.Capabilities;
import mekanism.common.capabilities.CapabilityWrapperManager;
import mekanism.common.config.MekanismConfig.general;
import mekanism.common.integration.forgeenergy.ForgeEnergyCableIntegration;
import mekanism.common.integration.tesla.TeslaCableIntegration;
import mekanism.common.transmitters.grid.EnergyNetwork;
import mekanism.common.util.CableUtils;
import mekanism.common.util.CapabilityUtils;
import mekanism.common.util.MekanismUtils;
import net.darkhax.tesla.api.ITeslaProducer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import cofh.api.energy.IEnergyProvider;
import cofh.api.energy.IEnergyReceiver;
public class TileEntityUniversalCable extends TileEntityTransmitter<EnergyAcceptorWrapper, EnergyNetwork> implements IStrictEnergyAcceptor, IStrictEnergyStorage, IEnergyReceiver
{
public Tier.CableTier tier = CableTier.BASIC;
public double currentPower = 0;
public double lastWrite = 0;
public EnergyStack buffer = new EnergyStack(0);
@Override
public BaseTier getBaseTier()
{
return tier.getBaseTier();
}
@Override
public void setBaseTier(BaseTier baseTier)
{
tier = Tier.CableTier.get(baseTier);
}
@Override
public void update()
{
if(getWorld().isRemote)
{
double targetPower = getTransmitter().hasTransmitterNetwork() ? getTransmitter().getTransmitterNetwork().clientEnergyScale : 0;
if(Math.abs(currentPower - targetPower) > 0.01)
{
currentPower = (9 * currentPower + targetPower) / 10;
}
}
else {
updateShare();
List<EnumFacing> sides = getConnections(ConnectionType.PULL);
if(!sides.isEmpty())
{
TileEntity[] connectedOutputters = CableUtils.getConnectedOutputters(getPos(), getWorld());
double canDraw = tier.cableCapacity;
for(EnumFacing side : sides)
{
if(connectedOutputters[side.ordinal()] != null)
{
TileEntity outputter = connectedOutputters[side.ordinal()];
if(CapabilityUtils.hasCapability(outputter, Capabilities.ENERGY_OUTPUTTER_CAPABILITY, side.getOpposite()) && CapabilityUtils.hasCapability(outputter, Capabilities.ENERGY_STORAGE_CAPABILITY, side.getOpposite()))
{
IStrictEnergyStorage storage = CapabilityUtils.getCapability(outputter, Capabilities.ENERGY_STORAGE_CAPABILITY, side.getOpposite());
double received = Math.min(storage.getEnergy(), canDraw);
double toDraw = received;
if(received > 0)
{
toDraw -= takeEnergy(received, true);
}
storage.setEnergy(storage.getEnergy() - toDraw);
}
else if(MekanismUtils.useTesla() && CapabilityUtils.hasCapability(outputter, Capabilities.TESLA_PRODUCER_CAPABILITY, side.getOpposite()))
{
ITeslaProducer producer = CapabilityUtils.getCapability(outputter, Capabilities.TESLA_PRODUCER_CAPABILITY, side.getOpposite());
double toDraw = producer.takePower((long)Math.round(Math.min(Integer.MAX_VALUE, canDraw*general.TO_TESLA)), true)*general.FROM_TESLA;
if(toDraw > 0)
{
toDraw -= takeEnergy(toDraw, true);
}
producer.takePower((long)Math.round(toDraw*general.TO_TESLA), false);
}
else if(MekanismUtils.useForge() && CapabilityUtils.hasCapability(outputter, CapabilityEnergy.ENERGY, side.getOpposite()))
{
IEnergyStorage storage = CapabilityUtils.getCapability(outputter, CapabilityEnergy.ENERGY, side.getOpposite());
double toDraw = storage.extractEnergy((int)Math.round(canDraw*general.TO_FORGE), true)*general.FROM_FORGE;
if(toDraw > 0)
{
toDraw -= takeEnergy(toDraw, true);
}
storage.extractEnergy((int)Math.round(toDraw*general.TO_TESLA), false);
}
else if(MekanismUtils.useRF() && outputter instanceof IEnergyProvider)
{
double toDraw = ((IEnergyProvider)outputter).extractEnergy(side.getOpposite(), (int)Math.round(Math.min(Integer.MAX_VALUE, canDraw*general.TO_RF)), true)*general.FROM_RF;
if(toDraw > 0)
{
toDraw -= takeEnergy(toDraw, true);
}
((IEnergyProvider)outputter).extractEnergy(side.getOpposite(), (int)Math.round(toDraw*general.TO_RF), false);
}
else if(MekanismUtils.useIC2())
{
IEnergyTile tile = EnergyNet.instance.getSubTile(outputter.getWorld(), outputter.getPos());
if(tile instanceof IEnergySource)
{
double received = Math.min(((IEnergySource)tile).getOfferedEnergy()*general.FROM_IC2, canDraw);
double toDraw = received;
if(received > 0)
{
toDraw -= takeEnergy(received, true);
}
((IEnergySource)tile).drawEnergy(toDraw*general.TO_IC2);
}
}
}
}
}
}
super.update();
}
@Override
public void updateShare()
{
if(getTransmitter().hasTransmitterNetwork() && getTransmitter().getTransmitterNetworkSize() > 0)
{
double last = getSaveShare();
if(last != lastWrite)
{
lastWrite = last;
markDirty();
}
}
}
private double getSaveShare()
{
if(getTransmitter().hasTransmitterNetwork())
{
return EnergyNetwork.round(getTransmitter().getTransmitterNetwork().buffer.amount * (1F / getTransmitter().getTransmitterNetwork().transmitters.size()));
}
else {
return buffer.amount;
}
}
@Override
public TransmitterType getTransmitterType()
{
return TransmitterType.UNIVERSAL_CABLE;
}
@Override
public void readFromNBT(NBTTagCompound nbtTags)
{
super.readFromNBT(nbtTags);
buffer.amount = nbtTags.getDouble("cacheEnergy");
if(buffer.amount < 0) buffer.amount = 0;
if(nbtTags.hasKey("tier")) tier = Tier.CableTier.values()[nbtTags.getInteger("tier")];
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbtTags)
{
super.writeToNBT(nbtTags);
nbtTags.setDouble("cacheEnergy", lastWrite);
nbtTags.setInteger("tier", tier.ordinal());
return nbtTags;
}
@Override
public TransmissionType getTransmissionType()
{
return TransmissionType.ENERGY;
}
@Override
public EnergyNetwork createNetworkByMerging(Collection<EnergyNetwork> networks)
{
return new EnergyNetwork(networks);
}
@Override
public boolean isValidAcceptor(TileEntity acceptor, EnumFacing side)
{
return CableUtils.isValidAcceptorOnSide(getWorld().getTileEntity(getPos()), acceptor, side);
}
@Override
public EnergyNetwork createNewNetwork()
{
return new EnergyNetwork();
}
@Override
public Object getBuffer()
{
return buffer;
}
@Override
public void takeShare()
{
if(getTransmitter().hasTransmitterNetwork())
{
getTransmitter().getTransmitterNetwork().buffer.amount -= lastWrite;
buffer.amount = lastWrite;
}
}
@Override
public int receiveEnergy(EnumFacing from, int maxReceive, boolean simulate)
{
return maxReceive - (int)Math.round(Math.min(Integer.MAX_VALUE, takeEnergy(maxReceive*general.FROM_RF, !simulate)*general.TO_RF));
}
@Override
public boolean canConnectEnergy(EnumFacing from)
{
return canConnect(from);
}
@Override
public int getEnergyStored(EnumFacing from)
{
return (int)Math.round(Math.min(Integer.MAX_VALUE, getEnergy()*general.TO_RF));
}
@Override
public int getMaxEnergyStored(EnumFacing from)
{
return (int)Math.round(Math.min(Integer.MAX_VALUE, getMaxEnergy()*general.TO_RF));
}
@Override
public int getCapacity()
{
return tier.cableCapacity;
}
@Override
public double acceptEnergy(EnumFacing side, double amount, boolean simulate)
{
if(!canReceiveEnergy(side))
{
return 0;
}
double toUse = Math.min(getMaxEnergy() - getEnergy(), amount);
if(!simulate)
{
setEnergy(getEnergy() + toUse);
}
return toUse;
}
@Override
public boolean canReceiveEnergy(EnumFacing side)
{
if(side == null)
{
return true;
}
return getConnectionType(side) == ConnectionType.NORMAL;
}
@Override
public double getMaxEnergy()
{
if(getTransmitter().hasTransmitterNetwork())
{
return getTransmitter().getTransmitterNetwork().getCapacity();
}
else {
return getCapacity();
}
}
@Override
public double getEnergy()
{
if(getTransmitter().hasTransmitterNetwork())
{
return getTransmitter().getTransmitterNetwork().buffer.amount;
}
else {
return buffer.amount;
}
}
@Override
public void setEnergy(double energy)
{
if(getTransmitter().hasTransmitterNetwork())
{
getTransmitter().getTransmitterNetwork().buffer.amount = energy;
}
else {
buffer.amount = energy;
}
}
public double takeEnergy(double energy, boolean doEmit)
{
if(getTransmitter().hasTransmitterNetwork())
{
return getTransmitter().getTransmitterNetwork().emit(energy, doEmit);
}
else {
double used = Math.min(getCapacity() - buffer.amount, energy);
if(doEmit)
{
buffer.amount += used;
}
return energy - used;
}
}
@Override
public EnergyAcceptorWrapper getCachedAcceptor(EnumFacing side)
{
return EnergyAcceptorWrapper.get(getCachedTile(side), side.getOpposite());
}
@Override
public boolean upgrade(int tierOrdinal)
{
if(tier.ordinal() < BaseTier.ULTIMATE.ordinal() && tierOrdinal == tier.ordinal()+1)
{
tier = CableTier.values()[tier.ordinal()+1];
markDirtyTransmitters();
sendDesc = true;
return true;
}
return false;
}
@Override
public void handlePacketData(ByteBuf dataStream) throws Exception
{
tier = CableTier.values()[dataStream.readInt()];
super.handlePacketData(dataStream);
}
@Override
public ArrayList<Object> getNetworkedData(ArrayList<Object> data)
{
data.add(tier.ordinal());
super.getNetworkedData(data);
return data;
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
return capability == Capabilities.ENERGY_STORAGE_CAPABILITY
|| capability == Capabilities.ENERGY_ACCEPTOR_CAPABILITY
|| capability == Capabilities.TESLA_CONSUMER_CAPABILITY
|| capability == CapabilityEnergy.ENERGY
|| super.hasCapability(capability, facing);
}
private CapabilityWrapperManager teslaManager = new CapabilityWrapperManager(getClass(), TeslaCableIntegration.class);
private CapabilityWrapperManager forgeEnergyManager = new CapabilityWrapperManager(getClass(), ForgeEnergyCableIntegration.class);
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if(capability == Capabilities.ENERGY_STORAGE_CAPABILITY || capability == Capabilities.ENERGY_ACCEPTOR_CAPABILITY)
{
return (T)this;
}
if(capability == Capabilities.TESLA_CONSUMER_CAPABILITY)
{
return (T)teslaManager.getWrapper(this, facing);
}
if(capability == CapabilityEnergy.ENERGY)
{
return (T)forgeEnergyManager.getWrapper(this, facing);
}
return super.getCapability(capability, facing);
}
}