package net.qbar.common.grid;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Nonnull;

import net.qbar.common.steam.ISteamHandler;
import net.qbar.common.steam.SteamTank;

public class SteamGrid extends CableGrid
{
    private int                    transferCapacity;
    private final SteamTank        tank;

    private final List<ISteamPipe> connectedPipes;

    public SteamGrid(final int identifier, final int transferCapacity)
    {
        super(identifier);
        this.transferCapacity = transferCapacity;

        this.connectedPipes = new ArrayList<>();

        this.tank = new SteamTank(0, 0, 1.5f);
    }

    @Override
    void tick()
    {
        super.tick();

        final Set<ISteamHandler> handlers = this.connectedPipes.stream()
                .flatMap(pipe -> pipe.getConnectedHandlers().stream()).collect(Collectors.toSet());
        handlers.add(this.tank);

        final double average = handlers.stream().mapToDouble(handler -> handler.getPressure()).average().orElse(0);

        final ISteamHandler[] above = handlers.stream().filter(handler -> handler.getPressure() - average > 0)
                .toArray(ISteamHandler[]::new);
        final ISteamHandler[] below = handlers.stream().filter(handler -> handler.getPressure() - average < 0)
                .toArray(ISteamHandler[]::new);

        final int drained = Stream.of(above).mapToInt(handler ->
        {
            return handler.drainSteam(
                    Math.min((int) ((handler.getPressure() - average) * handler.getCapacity()), this.transferCapacity),
                    false);
        }).sum();
        int filled = 0;

        for (final ISteamHandler handler : below)
            filled += handler.fillSteam(
                    Math.max(drained / below.length, Math.min(
                            (int) ((handler.getPressure() - average) * handler.getCapacity()), this.transferCapacity)),
                    true);

        for (final ISteamHandler handler : above)
            handler.drainSteam(
                    Math.max(filled / above.length, Math.min(
                            (int) ((handler.getPressure() - average) * handler.getCapacity()), this.transferCapacity)),
                    true);
    }

    public SteamTank getTank()
    {
        return this.tank;
    }

    public boolean isEmpty()
    {
        return this.tank.getSteam() == 0;
    }

    public int getCapacity()
    {
        return this.getCables().size() * this.getTransferCapacity();
    }

    public int getTransferCapacity()
    {
        return this.transferCapacity;
    }

    public void setTransferCapacity(final int transferCapacity)
    {
        this.transferCapacity = transferCapacity;
    }

    public void addConnectedPipe(final ISteamPipe pipe)
    {
        this.connectedPipes.add(pipe);
    }

    public void removeConnectedPipe(final ISteamPipe pipe)
    {
        this.connectedPipes.remove(pipe);
    }

    @Override
    public void addCable(@Nonnull final ITileCable cable)
    {
        super.addCable(cable);
        this.getTank().setCapacity(this.getCapacity());
    }

    @Override
    public boolean removeCable(final ITileCable cable)
    {
        if (super.removeCable(cable))
        {
            this.getTank().setCapacity(this.getCapacity());
            return true;
        }
        return false;
    }
}

@@ -726,32 +726,1198 @@
 , 1.5f);%0A    %7D%0A%0A
+    @Override%0A    CableGrid copy(final int identifier)%0A    %7B%0A        return new SteamGrid(identifier, this.transferCapacity);%0A    %7D%0A%0A    @Override%0A    void applyData(final CableGrid grid)%0A    %7B%0A        if (grid instanceof SteamGrid)%0A        %7B%0A            this.transferCapacity = ((SteamGrid) grid).getTransferCapacity();%0A        %7D%0A    %7D%0A%0A    @Override%0A    boolean canMerge(final CableGrid grid)%0A    %7B%0A        if (grid instanceof SteamGrid && ((SteamGrid) grid).getTransferCapacity() == this.transferCapacity)%0A            return super.canMerge(grid);%0A        return false;%0A    %7D%0A%0A    @Override%0A    void onMerge(final CableGrid grid)%0A    %7B%0A        this.getTank().setCapacity(this.getCapacity());%0A        if (((SteamGrid) grid).getTank().getSteam() != 0)%0A            this.getTank().fillInternal(((SteamGrid) grid).getTank().getSteam(), true);%0A    %7D%0A%0A    @Override%0A    void onSplit(final CableGrid grid)%0A    %7B%0A        this.getTank()%0A                .fillInternal(((SteamGrid) grid).getTank().drainInternal(%0A                        ((SteamGrid) grid).getTank().getSteam() / grid.getCables().size() * this.getCables().size(),%0A                        false), true);%0A    %7D%0A%0A
     @Override%0A  

Add merge and split for SteamGrid