Power system re-write, recipe fixes.

Please note that this version breaks all wires placed in worlds before.
This commit is contained in:
Dragon2488 2016-07-18 11:57:52 +07:00
parent 25c581e129
commit d982cc4028
33 changed files with 507 additions and 859 deletions

View file

@ -0,0 +1,241 @@
package techreborn.power;
import cofh.api.energy.IEnergyReceiver;
import com.google.common.collect.Lists;
import ic2.api.energy.tile.IEnergySink;
import net.darkhax.tesla.api.ITeslaConsumer;
import net.darkhax.tesla.capability.TeslaCapabilities;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Loader;
import reborncore.api.power.IEnergyInterfaceTile;
import reborncore.common.RebornCoreConfig;
import reborncore.common.powerSystem.TilePowerAcceptor;
import reborncore.mcmultipart.block.TileMultipartContainer;
import reborncore.mcmultipart.multipart.ISlottedPart;
import reborncore.mcmultipart.multipart.PartSlot;
import techreborn.parts.powerCables.CableMultipart;
import techreborn.parts.powerCables.EnumCableType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.BiFunction;
public class PowerNet {
/**
* Same as {@link #dispatchEnergyPacketRecursively(World, ArrayList, BlockPos, boolean, double)}
* But not simulated and excluding source block
* @param world the world to dispatch in
* @param energyAmount energy units to dispatch
* @return dispatched energy units
*/
public static double dispatchEnergyPacket(World world, BlockPos source, double energyAmount) {
return dispatchEnergyPacketRecursively(world, Lists.newArrayList(source), source, false, energyAmount);
}
/**
* Dispatches energy packet recursively through wires to all connected decives
* @param world the world to dispatch in
* @param excludes blocks to exclude from checking. as example, start block
* @param blockPos block pos to start checking
* @param maxEnergy energy units to dispatch
* @param simulate true if dispatch is only simulated
* @return dispatched energy units
*/
public static double dispatchEnergyPacketRecursively(World world, ArrayList<BlockPos> excludes, BlockPos blockPos, boolean simulate, final double maxEnergy) {
double energyLeft = maxEnergy;
Collection<EnumFacing> connections = Lists.newArrayList(EnumFacing.VALUES);
//Workaround for multipart cables
CableMultipart selfCable = getWire(world, blockPos);
if(selfCable != null) {
connections = selfCable.connectedSides.keySet();
}
TileEntity tileEntity = world.getTileEntity(blockPos);
if(tileEntity instanceof TilePowerAcceptor) {
for(EnumFacing facing : EnumFacing.VALUES) {
if(!((TilePowerAcceptor) tileEntity).canProvideEnergy(facing))
connections.remove(facing);
}
}
for(EnumFacing facing : connections) {
BlockPos offsetPos = blockPos.offset(facing);
if(!excludes.contains(offsetPos)) {
excludes.add(offsetPos);
if(isWire(world, offsetPos)) {
CableMultipart cable = getWire(world, offsetPos);
EnumCableType cableType = cable.getCableType();
double transferRate = cableType.transferRate;
double maxPacket = transferRate > maxEnergy ? maxEnergy : transferRate;
energyLeft -= dispatchEnergyPacketRecursively(world, excludes, offsetPos, simulate, maxPacket);
if(energyLeft == 0) {
if(selfCable != null)
selfCable.lastEnergyPacket = maxEnergy * 1.3F;
return maxEnergy;
}
} else {
PowerNetReceiver receiver = getReceiver(world, facing.getOpposite(), offsetPos);
if(receiver != null) {
energyLeft -= receiver.receiveEnergy(energyLeft, simulate);
if(energyLeft == 0) {
if(selfCable != null)
selfCable.lastEnergyPacket = maxEnergy * 1.3F;
return maxEnergy;
}
}
}
}
}
double energyDispatched = maxEnergy - energyLeft;
if(selfCable != null)
selfCable.lastEnergyPacket = energyDispatched * 1.3F;
return energyDispatched;
}
//////////////////// Wire utilities ////////////////////
public static boolean isWire(World world, BlockPos blockPos) {
return getWire(world, blockPos) != null;
}
public static CableMultipart getWire(World world, BlockPos pos) {
TileEntity tileEntity = world.getTileEntity(pos);
if(tileEntity instanceof TileMultipartContainer) {
TileMultipartContainer multipart = (TileMultipartContainer) tileEntity;
ISlottedPart centerPart = multipart.getPartInSlot(PartSlot.CENTER);
if(centerPart instanceof CableMultipart)
return (CableMultipart) centerPart;
}
return null;
}
//////////////////// Power Net Sources functionality ////////////////////
//TODO
//////////////////// Power Net Receivers functionality ////////////////////
public static PowerNetReceiver getReceiver(World world, EnumFacing side, BlockPos pos) {
TileEntity tileEntity = world.getTileEntity(pos);
if(Loader.isModLoaded("IC2") && RebornCoreConfig.getRebornPower().eu()) {
PowerNetReceiver ic2receiver = getIC2Receiver(tileEntity, side);
if(ic2receiver != null) return ic2receiver;
}
if(Loader.isModLoaded("Tesla") && RebornCoreConfig.getRebornPower().tesla()) {
PowerNetReceiver teslaReceiver = getTeslaReceiver(tileEntity, side);
if(teslaReceiver != null) return teslaReceiver;
}
if(RebornCoreConfig.getRebornPower().rf()) {
PowerNetReceiver rfReceiver = getRFReceiver(tileEntity, side);
if(rfReceiver != null) return rfReceiver;
}
if(RebornCoreConfig.getRebornPower().internal()) {
PowerNetReceiver internalReceiver = getInternalReceiver(tileEntity, side);
if(internalReceiver != null) return internalReceiver;
}
return null;
}
public static PowerNetReceiver getInternalReceiver(TileEntity tileEntity, EnumFacing side) {
if(tileEntity instanceof IEnergyInterfaceTile) {
IEnergyInterfaceTile energyInterface = (IEnergyInterfaceTile) tileEntity;
return new PowerNetReceiver(
(energy, simulated) -> {
if(energyInterface.canAcceptEnergy(side))
return energyInterface.addEnergy(energy, simulated);
return 0.0;
});
}
return null;
}
public static PowerNetReceiver getIC2Receiver(TileEntity tileEntity, EnumFacing side) {
if(tileEntity instanceof IEnergySink) {
IEnergySink acceptor = (IEnergySink) tileEntity;
return new PowerNetReceiver(
(energy, simulated) -> {
if(simulated) {
double max = acceptor.getDemandedEnergy();
return max > energy ? energy : max;
}
return energy - acceptor.injectEnergy(side, energy, acceptor.getSinkTier());
});
}
return null;
}
public static PowerNetReceiver getTeslaReceiver(TileEntity tileEntity, EnumFacing side) {
if(tileEntity.hasCapability(TeslaCapabilities.CAPABILITY_CONSUMER, side)) {
ITeslaConsumer consumer = tileEntity.getCapability(TeslaCapabilities.CAPABILITY_CONSUMER, side);
return new PowerNetReceiver(
(energy, simulated) -> {
long teslaEnergy = eu2tesla(energy);
return tesla2eu(consumer.givePower(teslaEnergy, simulated));
});
}
return null;
}
public static PowerNetReceiver getRFReceiver(TileEntity tileEntity, EnumFacing side) {
if(tileEntity instanceof IEnergyReceiver) {
IEnergyReceiver receiver = (IEnergyReceiver) tileEntity;
return new PowerNetReceiver(
(energy, simulated) -> {
int rfEnergy = eu2rf(energy);
return rf2eu(receiver.receiveEnergy(side, rfEnergy, simulated));
});
}
return null;
}
//////////////////// Energy Conversion utils ////////////////////
public static double rf2eu(int rf) {
return rf / 4F;
}
public static int eu2rf(double eu) {
return (int) Math.floor(eu * 4F);
}
public static long eu2tesla(double eu) {
return (long) Math.floor(eu / 3.75F);
}
public static double tesla2eu(long tesla) {
return tesla * 3.75F;
}
public static class PowerNetReceiver {
private final BiFunction<Double, Boolean, Double> receiveEnergy;
public PowerNetReceiver(BiFunction<Double, Boolean, Double> receiveEnergy) {
this.receiveEnergy = receiveEnergy;
}
/**
* Sends given amount fo EU to receiver
* @param max max eu to receive
* @return eu received
*/
public double receiveEnergy(double max, boolean simulated) {
return receiveEnergy.apply(max, simulated);
}
}
}

View file

@ -1,10 +0,0 @@
package techreborn.power;
import net.minecraftforge.fml.common.eventhandler.Event;
public class PowerTickEvent extends Event
{
public PowerTickEvent()
{
}
}

View file

@ -1,358 +0,0 @@
package techreborn.power;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import reborncore.api.power.IEnergyInterfaceTile;
import techreborn.parts.powerCables.CableMultipart;
import techreborn.parts.powerCables.EnumCableType;
public class TRPowerNet
{
public ArrayList<EnergyHandler> endpoints = new ArrayList();
int tick = 0;
EnumCableType cableType;
private ArrayList<CableMultipart> cables = new ArrayList();
private int energy = 0;
public TRPowerNet(EnumCableType cableType)
{
this.cableType = cableType;
MinecraftForge.EVENT_BUS.register(this);
}
public static void buildEndpoint(TRPowerNet net)
{
ArrayList<CableMultipart> parts = new ArrayList<>();
ArrayList<CableMultipart> partsToMerge = new ArrayList<>();
parts.addAll(net.cables);
for (CableMultipart cable : parts)
{
for (EnumFacing facing : EnumFacing.VALUES)
{
BlockPos pos = cable.getPos().offset(facing);
TileEntity tile = cable.getWorld().getTileEntity(pos);
if (tile != null && tile instanceof IEnergyInterfaceTile)
{
IEnergyInterfaceTile eit = (IEnergyInterfaceTile) tile;
net.addConnection(eit, facing);
}
CableMultipart cableMultipart = CableMultipart.getPartFromWorld(cable.getWorld(), pos, null);
if (cableMultipart != null)
{
if (cableMultipart.getNetwork() != net)
{
partsToMerge.add(cableMultipart);
}
}
}
}
for (CableMultipart cableMultipart : partsToMerge)
{
cableMultipart.mergeWith = net;
}
net.checkAndRemoveOldEndpoints();
}
public int getIOLimit()
{
return cableType.transferRate;
}
@SubscribeEvent
public void tick(PowerTickEvent evt)
{
if (tick < 20)
{
tick++;
return;
}
if (tick % 80 == 0)
{
List<CableMultipart> oldCables = new ArrayList<>();
for (CableMultipart cableMultipart : cables)
{
if (cableMultipart.getWorld() == null || cableMultipart.getPos() == null)
{
oldCables.add(cableMultipart);
}
CableMultipart mp = cableMultipart.getPartFromWorld(cableMultipart.getWorld(), cableMultipart.getPos(),
null);
if (mp == null)
{
oldCables.add(cableMultipart);
}
}
cables.removeAll(oldCables);
}
if (!cables.isEmpty())
{
ArrayList<EnergyHandler> collectibles = new ArrayList();
ArrayList<EnergyHandler> insertibles = new ArrayList();
for (EnergyHandler ei : endpoints)
{
if (ei.isCollectible())
{
collectibles.add(ei);
}
if (ei.isInsertible())
{
insertibles.add(ei);
}
}
if (energy < cableType.transferRate * cables.size())
{
for (EnergyHandler handler : collectibles)
{
energy += handler.collectEnergy(cableType.transferRate);
}
}
for (EnergyHandler handler : insertibles)
{
energy -= handler.addEnergy(Math.min(energy, cableType.transferRate));
}
} else
{
MinecraftForge.EVENT_BUS.unregister(this);
}
tick++;
}
public void addElement(CableMultipart te)
{
if (!cables.contains(te))
{
cables.add(te);
}
}
public void removeElement(CableMultipart te)
{
cables.remove(te);
this.rebuild();
this.checkAndRemoveOldEndpoints();
}
public void checkAndRemoveOldEndpoints()
{
List<EnergyHandler> deadHandlers = new ArrayList<>();
for (EnergyHandler energyHandler : endpoints)
{
TileEntity tile = (TileEntity) energyHandler.tile;
if (tile.getWorld().getTileEntity(tile.getPos()) == null)
{
deadHandlers.add(energyHandler);
} else
{
boolean hasNet = false;
for (EnumFacing facing : EnumFacing.VALUES)
{
BlockPos pos = tile.getPos().offset(facing);
CableMultipart multipart = CableMultipart.getPartFromWorld(tile.getWorld(), pos, facing);
if (multipart != null && multipart.getNetwork() == this)
{
hasNet = true;
}
}
if (!hasNet)
{
deadHandlers.add(energyHandler);
}
}
}
endpoints.removeAll(deadHandlers);
}
public void rebuild()
{
for (int i = 0; i < cables.size(); i++)
{
CableMultipart te = cables.get(i);
te.setNetwork(null);
te.findAndJoinNetwork(te.getWorld(), te.getPos());
}
this.clear(true);
MinecraftForge.EVENT_BUS.unregister(this);
}
public int getEnergy()
{
return energy;
}
public void setEnergy(int energy)
{
energy += energy;
if (energy < 0)
{
energy = 0;
}
}
public void addConnection(IEnergyInterfaceTile ih, EnumFacing dir)
{
if (ih instanceof CableMultipart)
return;
EnergyHandler has = this.getHandleFrom(ih);
if (has == null)
{
endpoints.add(new EnergyHandler(ih, cableType, dir));
} else
{
has.side = dir;
}
}
public void merge(TRPowerNet n)
{
if (n != this)
{
ArrayList<CableMultipart> li = new ArrayList();
for (int i = 0; i < n.cables.size(); i++)
{
CableMultipart wire = n.cables.get(i);
li.add(wire);
}
for (EnergyHandler ei : n.endpoints)
{
endpoints.add(ei);
}
n.clear(false);
for (int i = 0; i < li.size(); i++)
{
CableMultipart wire = li.get(i);
wire.setNetwork(this);
}
checkAndRemoveOldEndpoints();
MinecraftForge.EVENT_BUS.unregister(n);
}
}
private EnergyHandler getHandleFrom(IEnergyInterfaceTile tile)
{
for (EnergyHandler ei : endpoints)
{
if (ei.tile == tile)
return ei;
}
return null;
}
private void clear(boolean clearTiles)
{
if (clearTiles)
{
for (int i = 0; i < cables.size(); i++)
{
cables.get(i).resetNetwork();
}
}
cables.clear();
endpoints.clear();
energy = 0;
MinecraftForge.EVENT_BUS.unregister(this);
}
public int addEnergy(int maxAdd, boolean simulate)
{
if (energy >= this.getIOLimit())
return 0;
maxAdd = Math.min(this.getIOLimit(), maxAdd);
if (!simulate)
energy += maxAdd;
return maxAdd;
}
private static class EnergyHandler
{
private final IEnergyInterfaceTile tile;
private final EnumCableType type;
private EnumFacing side;
private EnergyHandler(IEnergyInterfaceTile ih, EnumCableType type, EnumFacing dir)
{
tile = ih;
this.type = type;
this.side = dir;
}
public boolean isInsertible()
{
return this.getTotalInsertible() > 0;
}
public boolean isCollectible()
{
return this.getTotalCollectible() > 0;
}
public boolean contains(IEnergyInterfaceTile tile)
{
return tile == this.tile;
}
public int collectEnergy(int max)
{
int total = 0;
if (tile.canProvideEnergy(side.getOpposite()))
{
int collect = (int) Math.min(max, Math.min(tile.getMaxOutput(), tile.getEnergy()));
total = (int) tile.useEnergy(collect, false);
}
return total;
}
public int addEnergy(int max)
{
int total = 0;
if (tile.canAcceptEnergy(side.getOpposite()) && max > 0)
{
if (type.tier.ordinal() > tile.getTier().ordinal() && max > tile.getMaxInput())
{
if (tile instanceof TileEntity)
{
((TileEntity) tile).getWorld().createExplosion(
new EntityTNTPrimed(((TileEntity) tile).getWorld()),
((TileEntity) tile).getPos().getX(), ((TileEntity) tile).getPos().getY(),
((TileEntity) tile).getPos().getZ(), 2.5F, true);
}
return 0;
}
int add = max - total;
total += tile.addEnergy(add, false);
}
return total;
}
public int getTotalCollectible()
{
if (tile.canProvideEnergy(side.getOpposite()) && tile.getEnergy() != 0)
{
return (int) Math.min(tile.getMaxOutput(), tile.getEnergy());
}
return 0;
}
public int getTotalInsertible()
{
int total = 0;
if (tile.canAcceptEnergy(side.getOpposite()) && tile.getMaxPower() - tile.getEnergy() != 0)
{
total += tile.addEnergy(type.transferRate, true);
}
return total;
}
}
}