Mekanism-tilera-Edition/src/main/java/mekanism/common/EnergyNetwork.java

467 lines
12 KiB
Java
Raw Normal View History

package mekanism.common;
import ic2.api.energy.EnergyNet;
import ic2.api.energy.tile.IEnergySink;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.api.MekanismConfig.general;
import mekanism.api.energy.IStrictEnergyAcceptor;
import mekanism.api.transmitters.DynamicNetwork;
2013-12-21 01:12:33 +01:00
import mekanism.api.transmitters.IGridTransmitter;
import mekanism.api.transmitters.TransmissionType;
import mekanism.api.util.ListUtils;
import mekanism.common.util.CableUtils;
import mekanism.common.util.MekanismUtils;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.MinecraftForge;
2014-06-02 23:57:40 +02:00
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.mj.IBatteryObject;
import buildcraft.api.mj.MjAPI;
import cofh.api.energy.IEnergyHandler;
import cpw.mods.fml.common.FMLCommonHandler;
2014-06-02 23:57:40 +02:00
import cpw.mods.fml.common.eventhandler.Event;
public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
{
private double lastPowerScale = 0;
private double joulesTransmitted = 0;
private double jouleBufferLastTick = 0;
public double clientEnergyScale = 0;
public double electricityStored;
2013-12-21 01:12:33 +01:00
public EnergyNetwork(IGridTransmitter<EnergyNetwork>... varCables)
{
transmitters.addAll(Arrays.asList(varCables));
register();
}
2013-12-21 01:12:33 +01:00
public EnergyNetwork(Collection<IGridTransmitter<EnergyNetwork>> collection)
{
transmitters.addAll(collection);
register();
}
2013-07-28 04:32:41 +02:00
public EnergyNetwork(Set<EnergyNetwork> networks)
{
2013-07-31 22:44:53 +02:00
for(EnergyNetwork net : networks)
2013-07-28 04:32:41 +02:00
{
if(net != null)
{
if(net.jouleBufferLastTick > jouleBufferLastTick || net.clientEnergyScale > clientEnergyScale)
2013-11-29 19:04:39 +01:00
{
clientEnergyScale = net.clientEnergyScale;
jouleBufferLastTick = net.jouleBufferLastTick;
2013-11-29 19:04:39 +01:00
joulesTransmitted = net.joulesTransmitted;
lastPowerScale = net.lastPowerScale;
}
electricityStored += net.electricityStored;
addAllTransmitters(net.transmitters);
2013-07-28 04:32:41 +02:00
net.deregister();
}
}
register();
2013-07-28 04:32:41 +02:00
}
public static double round(double d)
{
return Math.round(d * 10000)/10000;
}
@Override
protected synchronized void updateMeanCapacity()
{
int numCables = transmitters.size();
double reciprocalSum = 0;
2013-12-21 01:12:33 +01:00
for(IGridTransmitter<EnergyNetwork> cable : transmitters)
{
reciprocalSum += 1.0/(double)cable.getCapacity();
}
meanCapacity = (double)numCables / reciprocalSum;
}
@Override
public void onNetworksCreated(List<EnergyNetwork> networks)
{
if(FMLCommonHandler.instance().getEffectiveSide().isServer())
{
double[] caps = new double[networks.size()];
double cap = 0;
for(EnergyNetwork network : networks)
{
double networkCapacity = network.getCapacity();
caps[networks.indexOf(network)] = networkCapacity;
cap += networkCapacity;
}
electricityStored = Math.min(cap, electricityStored);
double[] percent = ListUtils.percent(caps);
for(EnergyNetwork network : networks)
{
network.electricityStored = round(percent[networks.indexOf(network)]*electricityStored);
}
}
}
public synchronized double getEnergyNeeded()
{
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{
return 0;
}
return getCapacity()-electricityStored;
}
public synchronized double tickEmit(double energyToSend)
2013-11-17 16:55:20 +01:00
{
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{
return 0;
}
double sent = 0;
boolean tryAgain = false;
int i = 0;
do {
2014-08-08 05:48:22 +02:00
double prev = sent;
2014-08-09 19:29:04 +02:00
sent += doEmit(energyToSend-sent, tryAgain);
2014-08-08 05:48:22 +02:00
tryAgain = energyToSend-sent > 0 && sent-prev > 0 && i < 100;
i++;
} while(tryAgain);
joulesTransmitted = sent;
return sent;
2013-11-17 16:55:20 +01:00
}
public synchronized double emit(double energyToSend)
{
double toUse = Math.min(getEnergyNeeded(), energyToSend);
electricityStored += toUse;
return energyToSend-toUse;
}
/**
* @return sent
*/
2014-08-09 19:29:04 +02:00
public synchronized double doEmit(double energyToSend, boolean tryAgain)
{
double sent = 0;
2013-08-18 22:51:47 +02:00
List availableAcceptors = Arrays.asList(getAcceptors().toArray());
Collections.shuffle(availableAcceptors);
if(!availableAcceptors.isEmpty())
{
int divider = availableAcceptors.size();
double remaining = energyToSend % divider;
double sending = (energyToSend-remaining)/divider;
for(Object obj : availableAcceptors)
{
if(obj instanceof TileEntity)
{
TileEntity acceptor = (TileEntity)obj;
double currentSending = sending+remaining;
EnumSet<ForgeDirection> sides = acceptorDirections.get(Coord4D.get(acceptor));
if(sides == null || sides.isEmpty())
2013-12-03 22:57:57 +01:00
{
continue;
}
for(ForgeDirection side : sides)
{
double prev = sent;
if(acceptor instanceof IStrictEnergyAcceptor)
{
sent += ((IStrictEnergyAcceptor)acceptor).transferEnergyToAcceptor(side.getOpposite(), currentSending);
}
else if(MekanismUtils.useRF() && acceptor instanceof IEnergyHandler)
{
IEnergyHandler handler = (IEnergyHandler)acceptor;
int used = handler.receiveEnergy(side.getOpposite(), (int)Math.round(currentSending*general.TO_TE), false);
sent += used*general.FROM_TE;
}
else if(MekanismUtils.useIC2() && acceptor instanceof IEnergySink)
{
double toSend = Math.min(currentSending, EnergyNet.instance.getPowerFromTier(((IEnergySink)acceptor).getSinkTier())*general.FROM_IC2);
toSend = Math.min(toSend, ((IEnergySink)acceptor).getDemandedEnergy()*general.FROM_IC2);
sent += (toSend - (((IEnergySink)acceptor).injectEnergy(side.getOpposite(), toSend*general.TO_IC2, 0)*general.FROM_IC2));
}
else if(MekanismUtils.useBuildCraft() && MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite()) != null && !tryAgain)
{
IBatteryObject battery = MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite());
double toSend = battery.addEnergy(Math.min(battery.getEnergyRequested(), currentSending*general.TO_BC));
sent += toSend*general.FROM_BC;
}
if(sent > prev)
{
break;
}
}
}
}
}
return sent;
}
2013-08-18 22:51:47 +02:00
@Override
public synchronized Set<TileEntity> getAcceptors(Object... data)
{
Set<TileEntity> toReturn = new HashSet<TileEntity>();
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{
return toReturn;
}
for(Coord4D coord : ((Map<Coord4D, TileEntity>)possibleAcceptors.clone()).keySet())
{
EnumSet<ForgeDirection> sides = acceptorDirections.get(coord);
TileEntity acceptor = coord.getTileEntity(getWorld());
if(sides == null || sides.isEmpty())
{
continue;
}
for(ForgeDirection side : sides)
{
if(acceptor instanceof IStrictEnergyAcceptor)
{
IStrictEnergyAcceptor handler = (IStrictEnergyAcceptor)acceptor;
if(handler.canReceiveEnergy(side.getOpposite()))
{
if(handler.getMaxEnergy() - handler.getEnergy() > 0)
{
toReturn.add(acceptor);
break;
}
}
}
else if(MekanismUtils.useRF() && acceptor instanceof IEnergyHandler)
{
IEnergyHandler handler = (IEnergyHandler)acceptor;
if(handler.canConnectEnergy(side.getOpposite()))
{
if(handler.receiveEnergy(side.getOpposite(), 1, true) > 0)
{
toReturn.add(acceptor);
break;
}
}
}
else if(MekanismUtils.useIC2() && acceptor instanceof IEnergySink)
{
IEnergySink handler = (IEnergySink)acceptor;
if(handler.acceptsEnergyFrom(null, side.getOpposite()))
{
double demanded = handler.getDemandedEnergy()*general.FROM_IC2;
int tier = Math.min(handler.getSinkTier(), 8);
double max = EnergyNet.instance.getPowerFromTier(tier)*general.FROM_IC2;
if(Math.min(demanded, max) > 0)
{
toReturn.add(acceptor);
break;
}
}
}
else if(MekanismUtils.useBuildCraft() && MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite()) != null)
{
IBatteryObject battery = MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite());
if(battery.getEnergyRequested() > 0)
{
toReturn.add(acceptor);
break;
}
}
}
}
return toReturn;
}
2013-08-18 22:51:47 +02:00
@Override
public synchronized void refresh()
{
2013-12-21 01:12:33 +01:00
Set<IGridTransmitter<EnergyNetwork>> iterCables = (Set<IGridTransmitter<EnergyNetwork>>)transmitters.clone();
Iterator<IGridTransmitter<EnergyNetwork>> it = iterCables.iterator();
boolean networkChanged = false;
while(it.hasNext())
{
2013-12-21 01:12:33 +01:00
IGridTransmitter<EnergyNetwork> conductor = (IGridTransmitter<EnergyNetwork>)it.next();
if(conductor == null || conductor.getTile().isInvalid())
{
it.remove();
transmitters.remove(conductor);
networkChanged = true;
}
else {
conductor.setTransmitterNetwork(this);
}
}
if(networkChanged)
{
updateCapacity();
}
2013-11-03 22:54:33 +01:00
needsUpdate = true;
}
@Override
public synchronized void refresh(IGridTransmitter<EnergyNetwork> transmitter)
{
TileEntity[] acceptors = CableUtils.getConnectedEnergyAcceptors(transmitter.getTile());
clearAround(transmitter);
for(TileEntity acceptor : acceptors)
{
ForgeDirection side = ForgeDirection.getOrientation(Arrays.asList(acceptors).indexOf(acceptor));
if(side != null && acceptor != null && !(acceptor instanceof IGridTransmitter) && transmitter.canConnectToAcceptor(side, true))
{
possibleAcceptors.put(Coord4D.get(acceptor), acceptor);
addSide(Coord4D.get(acceptor), ForgeDirection.getOrientation(Arrays.asList(acceptors).indexOf(acceptor)));
}
}
}
public static class EnergyTransferEvent extends Event
{
public final EnergyNetwork energyNetwork;
public final double power;
public EnergyTransferEvent(EnergyNetwork network, double currentPower)
{
energyNetwork = network;
power = currentPower;
}
}
@Override
public String toString()
{
return "[EnergyNetwork] " + transmitters.size() + " transmitters, " + possibleAcceptors.size() + " acceptors.";
}
2013-08-18 22:51:47 +02:00
@Override
2013-12-21 20:54:12 +01:00
public void onUpdate()
{
2013-12-21 20:54:12 +01:00
super.onUpdate();
clearJoulesTransmitted();
double currentPowerScale = getPowerScale();
2013-11-03 22:54:33 +01:00
if(FMLCommonHandler.instance().getEffectiveSide().isServer())
{
if(Math.abs(currentPowerScale-lastPowerScale) > 0.01 || (currentPowerScale != lastPowerScale && (currentPowerScale == 0 || currentPowerScale == 1)))
2013-11-03 22:54:33 +01:00
{
needsUpdate = true;
}
2013-11-03 22:54:33 +01:00
if(needsUpdate)
{
MinecraftForge.EVENT_BUS.post(new EnergyTransferEvent(this, currentPowerScale));
lastPowerScale = currentPowerScale;
2013-11-03 22:54:33 +01:00
needsUpdate = false;
}
if(electricityStored > 0)
{
electricityStored -= tickEmit(electricityStored);
}
}
}
public double getPowerScale()
{
return Math.max(jouleBufferLastTick == 0 ? 0 : Math.min(Math.ceil(Math.log10(getPower())*2)/10, 1), getCapacity() == 0 ? 0 : electricityStored/getCapacity());
2013-07-28 04:32:41 +02:00
}
public void clearJoulesTransmitted()
{
jouleBufferLastTick = electricityStored;
joulesTransmitted = 0;
}
public double getPower()
{
return jouleBufferLastTick * 20;
}
@Override
protected EnergyNetwork create(Collection<IGridTransmitter<EnergyNetwork>> collection)
{
2013-11-29 04:20:24 +01:00
EnergyNetwork network = new EnergyNetwork(collection);
network.clientEnergyScale = clientEnergyScale;
network.jouleBufferLastTick = jouleBufferLastTick;
2013-11-29 19:04:39 +01:00
network.joulesTransmitted = joulesTransmitted;
network.lastPowerScale = lastPowerScale;
network.electricityStored += electricityStored;
network.updateCapacity();
2013-11-29 04:20:24 +01:00
return network;
}
@Override
public TransmissionType getTransmissionType()
{
return TransmissionType.ENERGY;
}
@Override
public String getNeededInfo()
{
return MekanismUtils.getEnergyDisplay(getEnergyNeeded());
}
@Override
public String getStoredInfo()
{
return MekanismUtils.getEnergyDisplay(electricityStored);
}
@Override
public String getFlowInfo()
{
return MekanismUtils.getEnergyDisplay(joulesTransmitted) + "/t";
}
2013-07-28 04:32:41 +02:00
}