package mekanism.api; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import mekanism.common.MekanismUtils; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.Event; import cpw.mods.fml.common.FMLCommonHandler; public class GasNetwork extends DynamicNetwork { public GasNetwork(ITransmitter... varPipes) { transmitters.addAll(Arrays.asList(varPipes)); register(); } public GasNetwork(Collection> collection) { transmitters.addAll(collection); register(); } public GasNetwork(Set networks) { for(GasNetwork net : networks) { if(net != null) { addAllTransmitters(net.transmitters); net.deregister(); } } refresh(); register(); } public int emit(int gasToSend, EnumGas transferType, TileEntity emitter) { List availableAcceptors = Arrays.asList(getAcceptors(transferType).toArray()); Collections.shuffle(availableAcceptors); int prevSending = gasToSend; if(!availableAcceptors.isEmpty()) { int divider = availableAcceptors.size(); int remaining = gasToSend % divider; int sending = (gasToSend-remaining)/divider; for(Object obj : availableAcceptors) { if(obj instanceof IGasAcceptor && obj != emitter) { IGasAcceptor acceptor = (IGasAcceptor)obj; int currentSending = sending; if(remaining > 0) { currentSending++; remaining--; } gasToSend -= (currentSending - acceptor.transferGasToAcceptor(currentSending, transferType)); } } } if(prevSending > gasToSend && FMLCommonHandler.instance().getEffectiveSide().isServer()) { MinecraftForge.EVENT_BUS.post(new GasTransferEvent(this, transferType)); } return gasToSend; } @Override public Set getAcceptors(Object... data) { EnumGas transferType = (EnumGas)data[0]; Set toReturn = new HashSet(); for(IGasAcceptor acceptor : possibleAcceptors) { if(acceptor.canReceiveGas(acceptorDirections.get(acceptor).getOpposite(), transferType)) { if(!(acceptor instanceof IGasStorage) || (acceptor instanceof IGasStorage && (((IGasStorage)acceptor).getMaxGas(transferType) - ((IGasStorage)acceptor).getGas(transferType)) > 0)) { toReturn.add(acceptor); } } } return toReturn; } @Override public void refresh() { Set> iterTubes = (Set>)transmitters.clone(); Iterator> it = iterTubes.iterator(); possibleAcceptors.clear(); acceptorDirections.clear(); while(it.hasNext()) { ITransmitter conductor = (ITransmitter)it.next(); if(conductor == null || ((TileEntity)conductor).isInvalid()) { it.remove(); transmitters.remove(conductor); } else { conductor.setNetwork(this); } } for(ITransmitter pipe : transmitters) { IGasAcceptor[] acceptors = GasTransmission.getConnectedAcceptors((TileEntity)pipe); for(IGasAcceptor acceptor : acceptors) { if(acceptor != null && !(acceptor instanceof ITransmitter)) { possibleAcceptors.add(acceptor); acceptorDirections.put(acceptor, ForgeDirection.getOrientation(Arrays.asList(acceptors).indexOf(acceptor))); } } } } @Override public void merge(GasNetwork network) { if(network != null && network != this) { Set networks = new HashSet(); networks.add(this); networks.add(network); GasNetwork newNetwork = new GasNetwork(networks); newNetwork.refresh(); } } @Override public void split(ITransmitter splitPoint) { if(splitPoint instanceof TileEntity) { removeTransmitter(splitPoint); TileEntity[] connectedBlocks = new TileEntity[6]; boolean[] dealtWith = {false, false, false, false, false, false}; for(ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { TileEntity sideTile = Object3D.get((TileEntity)splitPoint).getFromSide(direction).getTileEntity(((TileEntity)splitPoint).worldObj); if(sideTile != null) { connectedBlocks[Arrays.asList(ForgeDirection.values()).indexOf(direction)] = sideTile; } } for(int countOne = 0; countOne < connectedBlocks.length; countOne++) { TileEntity connectedBlockA = connectedBlocks[countOne]; if(MekanismUtils.checkNetwork(connectedBlockA, GasNetwork.class) && !dealtWith[countOne]) { NetworkFinder finder = new NetworkFinder(((TileEntity)splitPoint).worldObj, getClass(), Object3D.get(connectedBlockA), Object3D.get((TileEntity)splitPoint)); List partNetwork = finder.exploreNetwork(); for(int countTwo = countOne + 1; countTwo < connectedBlocks.length; countTwo++) { TileEntity connectedBlockB = connectedBlocks[countTwo]; if(MekanismUtils.checkNetwork(connectedBlockB, GasNetwork.class) && !dealtWith[countTwo]) { if(partNetwork.contains(Object3D.get(connectedBlockB))) { dealtWith[countTwo] = true; } } } GasNetwork newNetwork = new GasNetwork(); for(Object3D node : finder.iterated) { TileEntity nodeTile = node.getTileEntity(((TileEntity)splitPoint).worldObj); if(MekanismUtils.checkNetwork(nodeTile, GasNetwork.class)) { if(nodeTile != splitPoint) { newNetwork.transmitters.add((ITransmitter)nodeTile); } } } newNetwork.refresh(); } } deregister(); } } public static class GasTransferEvent extends Event { public final GasNetwork gasNetwork; public final EnumGas transferType; public GasTransferEvent(GasNetwork network, EnumGas type) { gasNetwork = network; transferType = type; } } @Override public String toString() { return "[GasNetwork] " + transmitters.size() + " transmitters, " + possibleAcceptors.size() + " acceptors."; } @Override protected GasNetwork create(ITransmitter... varTransmitters) { return new GasNetwork(varTransmitters); } @Override protected GasNetwork create(Collection> collection) { return new GasNetwork(collection); } @Override protected GasNetwork create(Set networks) { return new GasNetwork(networks); } }