Search in sources :

Example 1 with Flow

use of com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow in project Create by Creators-of-Create.

the class FluidNetwork method tick.

public void tick() {
    if (pauseBeforePropagation > 0) {
        pauseBeforePropagation--;
        return;
    }
    for (int cycle = 0; cycle < CYCLES_PER_TICK; cycle++) {
        boolean shouldContinue = false;
        for (Iterator<BlockFace> iterator = queued.iterator(); iterator.hasNext(); ) {
            BlockFace blockFace = iterator.next();
            if (!isPresent(blockFace))
                continue;
            PipeConnection pipeConnection = get(blockFace);
            if (pipeConnection != null) {
                if (blockFace.equals(start))
                    transferSpeed = (int) Math.max(1, pipeConnection.pressure.get(true) / 2f);
                frontier.add(Pair.of(blockFace, pipeConnection));
            }
            iterator.remove();
        }
        for (Iterator<Pair<BlockFace, PipeConnection>> iterator = frontier.iterator(); iterator.hasNext(); ) {
            Pair<BlockFace, PipeConnection> pair = iterator.next();
            BlockFace blockFace = pair.getFirst();
            PipeConnection pipeConnection = pair.getSecond();
            if (!pipeConnection.hasFlow())
                continue;
            Flow flow = pipeConnection.flow.get();
            if (!fluid.isEmpty() && !flow.fluid.isFluidEqual(fluid)) {
                iterator.remove();
                continue;
            }
            if (!flow.inbound) {
                if (pipeConnection.comparePressure() >= 0)
                    iterator.remove();
                continue;
            }
            if (!flow.complete)
                continue;
            if (fluid.isEmpty())
                fluid = flow.fluid;
            boolean canRemove = true;
            for (Direction side : Iterate.directions) {
                if (side == blockFace.getFace())
                    continue;
                BlockFace adjacentLocation = new BlockFace(blockFace.getPos(), side);
                PipeConnection adjacent = get(adjacentLocation);
                if (adjacent == null)
                    continue;
                if (!adjacent.hasFlow()) {
                    // Branch could potentially still appear
                    if (adjacent.hasPressure() && adjacent.pressure.getSecond() > 0)
                        canRemove = false;
                    continue;
                }
                Flow outFlow = adjacent.flow.get();
                if (outFlow.inbound) {
                    if (adjacent.comparePressure() > 0)
                        canRemove = false;
                    continue;
                }
                if (!outFlow.complete) {
                    canRemove = false;
                    continue;
                }
                // Give pipe end a chance to init connections
                if (!adjacent.source.isPresent() && !adjacent.determineSource(world, blockFace.getPos())) {
                    canRemove = false;
                    continue;
                }
                if (adjacent.source.isPresent() && adjacent.source.get().isEndpoint()) {
                    targets.add(Pair.of(adjacentLocation, adjacent.source.get().provideHandler()));
                    continue;
                }
                if (visited.add(adjacentLocation.getConnectedPos())) {
                    queued.add(adjacentLocation.getOpposite());
                    shouldContinue = true;
                }
            }
            if (canRemove)
                iterator.remove();
        }
        if (!shouldContinue)
            break;
    }
    if (!source.isPresent())
        source = sourceSupplier.get();
    if (!source.isPresent())
        return;
    keepPortableFluidInterfaceEngaged();
    if (targets.isEmpty())
        return;
    for (Pair<BlockFace, LazyOptional<IFluidHandler>> pair : targets) {
        if (pair.getSecond().isPresent() && world.getGameTime() % 40 != 0)
            continue;
        PipeConnection pipeConnection = get(pair.getFirst());
        if (pipeConnection == null)
            continue;
        pipeConnection.source.ifPresent(fs -> {
            if (fs.isEndpoint())
                pair.setSecond(fs.provideHandler());
        });
    }
    int flowSpeed = transferSpeed;
    for (boolean simulate : Iterate.trueAndFalse) {
        FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE;
        IFluidHandler handler = source.orElse(null);
        if (handler == null)
            return;
        FluidStack transfer = FluidStack.EMPTY;
        for (int i = 0; i < handler.getTanks(); i++) {
            FluidStack contained = handler.getFluidInTank(i);
            if (contained.isEmpty())
                continue;
            if (!contained.isFluidEqual(fluid))
                continue;
            FluidStack toExtract = FluidHelper.copyStackWithAmount(contained, flowSpeed);
            transfer = handler.drain(toExtract, action);
        }
        if (transfer.isEmpty()) {
            FluidStack genericExtract = handler.drain(flowSpeed, action);
            if (!genericExtract.isEmpty() && genericExtract.isFluidEqual(fluid))
                transfer = genericExtract;
        }
        if (transfer.isEmpty())
            return;
        if (simulate)
            flowSpeed = transfer.getAmount();
        List<Pair<BlockFace, LazyOptional<IFluidHandler>>> availableOutputs = new ArrayList<>(targets);
        while (!availableOutputs.isEmpty() && transfer.getAmount() > 0) {
            int dividedTransfer = transfer.getAmount() / availableOutputs.size();
            int remainder = transfer.getAmount() % availableOutputs.size();
            for (Iterator<Pair<BlockFace, LazyOptional<IFluidHandler>>> iterator = availableOutputs.iterator(); iterator.hasNext(); ) {
                Pair<BlockFace, LazyOptional<IFluidHandler>> pair = iterator.next();
                int toTransfer = dividedTransfer;
                if (remainder > 0) {
                    toTransfer++;
                    remainder--;
                }
                if (transfer.isEmpty())
                    break;
                IFluidHandler targetHandler = pair.getSecond().orElse(null);
                if (targetHandler == null) {
                    iterator.remove();
                    continue;
                }
                FluidStack divided = transfer.copy();
                divided.setAmount(toTransfer);
                int fill = targetHandler.fill(divided, action);
                transfer.setAmount(transfer.getAmount() - fill);
                if (fill < toTransfer)
                    iterator.remove();
            }
        }
        flowSpeed -= transfer.getAmount();
        transfer = FluidStack.EMPTY;
    }
}
Also used : BlockFace(com.simibubi.create.foundation.utility.BlockFace) FluidStack(net.minecraftforge.fluids.FluidStack) ArrayList(java.util.ArrayList) FluidAction(net.minecraftforge.fluids.capability.IFluidHandler.FluidAction) Direction(net.minecraft.core.Direction) IFluidHandler(net.minecraftforge.fluids.capability.IFluidHandler) Flow(com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow) LazyOptional(net.minecraftforge.common.util.LazyOptional) Pair(com.simibubi.create.foundation.utility.Pair)

Example 2 with Flow

use of com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow in project Create by Creators-of-Create.

the class TransparentStraightPipeRenderer method renderSafe.

@Override
protected void renderSafe(StraightPipeTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) {
    FluidTransportBehaviour pipe = te.getBehaviour(FluidTransportBehaviour.TYPE);
    if (pipe == null)
        return;
    for (Direction side : Iterate.directions) {
        Flow flow = pipe.getFlow(side);
        if (flow == null)
            continue;
        FluidStack fluidStack = flow.fluid;
        if (fluidStack.isEmpty())
            continue;
        LerpedFloat progress = flow.progress;
        if (progress == null)
            continue;
        float value = progress.getValue(partialTicks);
        boolean inbound = flow.inbound;
        if (value == 1) {
            if (inbound) {
                Flow opposite = pipe.getFlow(side.getOpposite());
                if (opposite == null)
                    value -= 1e-6f;
            } else {
                FluidTransportBehaviour adjacent = TileEntityBehaviour.get(te.getLevel(), te.getBlockPos().relative(side), FluidTransportBehaviour.TYPE);
                if (adjacent == null)
                    value -= 1e-6f;
                else {
                    Flow other = adjacent.getFlow(side.getOpposite());
                    if (other == null || !other.inbound && !other.complete)
                        value -= 1e-6f;
                }
            }
        }
        FluidRenderer.renderFluidStream(fluidStack, side, 3 / 16f, value, inbound, buffer, ms, light);
    }
}
Also used : LerpedFloat(com.simibubi.create.foundation.utility.animation.LerpedFloat) FluidStack(net.minecraftforge.fluids.FluidStack) FluidTransportBehaviour(com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour) Direction(net.minecraft.core.Direction) Flow(com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow)

Example 3 with Flow

use of com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow in project Create by Creators-of-Create.

the class ContentObserverTileEntity method tick.

@Override
public void tick() {
    super.tick();
    BlockState state = getBlockState();
    if (turnOffTicks > 0) {
        turnOffTicks--;
        if (turnOffTicks == 0)
            level.scheduleTick(worldPosition, state.getBlock(), 1);
    }
    if (!isActive())
        return;
    Direction facing = state.getValue(ContentObserverBlock.FACING);
    BlockPos targetPos = worldPosition.relative(facing);
    // Detect items on belt
    TransportedItemStackHandlerBehaviour behaviour = TileEntityBehaviour.get(level, targetPos, TransportedItemStackHandlerBehaviour.TYPE);
    if (behaviour != null) {
        behaviour.handleCenteredProcessingOnAllItems(.45f, stack -> {
            if (!filtering.test(stack.stack) || turnOffTicks == 6)
                return TransportedResult.doNothing();
            activate();
            return TransportedResult.doNothing();
        });
        return;
    }
    // Detect fluids in pipe
    FluidTransportBehaviour fluidBehaviour = TileEntityBehaviour.get(level, targetPos, FluidTransportBehaviour.TYPE);
    if (fluidBehaviour != null) {
        for (Direction side : Iterate.directions) {
            Flow flow = fluidBehaviour.getFlow(side);
            if (flow == null || !flow.inbound || !flow.complete)
                continue;
            if (!filtering.test(flow.fluid))
                continue;
            activate();
            return;
        }
        return;
    }
    if (!observedInventory.simulate().extract().isEmpty()) {
        activate();
        return;
    }
    if (!observedTank.simulate().extractAny().isEmpty()) {
        activate();
        return;
    }
}
Also used : BlockState(net.minecraft.world.level.block.state.BlockState) BlockPos(net.minecraft.core.BlockPos) FluidTransportBehaviour(com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour) Direction(net.minecraft.core.Direction) TransportedItemStackHandlerBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour) Flow(com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow)

Example 4 with Flow

use of com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow in project Create by Creators-of-Create.

the class FluidPropagator method resetAffectedFluidNetworks.

public static void resetAffectedFluidNetworks(Level world, BlockPos start, Direction side) {
    List<BlockPos> frontier = new ArrayList<>();
    Set<BlockPos> visited = new HashSet<>();
    frontier.add(start);
    while (!frontier.isEmpty()) {
        BlockPos pos = frontier.remove(0);
        if (visited.contains(pos))
            continue;
        visited.add(pos);
        FluidTransportBehaviour pipe = getPipe(world, pos);
        if (pipe == null)
            continue;
        for (Direction d : Iterate.directions) {
            if (pos.equals(start) && d != side)
                continue;
            BlockPos target = pos.relative(d);
            if (visited.contains(target))
                continue;
            PipeConnection connection = pipe.getConnection(d);
            if (connection == null)
                continue;
            if (!connection.hasFlow())
                continue;
            Flow flow = connection.flow.get();
            if (!flow.inbound)
                continue;
            connection.resetNetwork();
            frontier.add(target);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) BlockPos(net.minecraft.core.BlockPos) Direction(net.minecraft.core.Direction) AxisDirection(net.minecraft.core.Direction.AxisDirection) HashSet(java.util.HashSet) Flow(com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow)

Aggregations

Flow (com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow)4 Direction (net.minecraft.core.Direction)4 FluidTransportBehaviour (com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour)2 ArrayList (java.util.ArrayList)2 BlockPos (net.minecraft.core.BlockPos)2 FluidStack (net.minecraftforge.fluids.FluidStack)2 TransportedItemStackHandlerBehaviour (com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour)1 BlockFace (com.simibubi.create.foundation.utility.BlockFace)1 Pair (com.simibubi.create.foundation.utility.Pair)1 LerpedFloat (com.simibubi.create.foundation.utility.animation.LerpedFloat)1 HashSet (java.util.HashSet)1 AxisDirection (net.minecraft.core.Direction.AxisDirection)1 BlockState (net.minecraft.world.level.block.state.BlockState)1 LazyOptional (net.minecraftforge.common.util.LazyOptional)1 IFluidHandler (net.minecraftforge.fluids.capability.IFluidHandler)1 FluidAction (net.minecraftforge.fluids.capability.IFluidHandler.FluidAction)1