Search in sources :

Example 1 with BlockFace

use of com.simibubi.create.foundation.utility.BlockFace 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 BlockFace

use of com.simibubi.create.foundation.utility.BlockFace in project Create by Creators-of-Create.

the class PumpTileEntity method distributePressureTo.

protected void distributePressureTo(Direction side) {
    if (getSpeed() == 0)
        return;
    BlockFace start = new BlockFace(worldPosition, side);
    boolean pull = isPullingOnSide(isFront(side));
    Set<BlockFace> targets = new HashSet<>();
    Map<BlockPos, Pair<Integer, Map<Direction, Boolean>>> pipeGraph = new HashMap<>();
    if (!pull)
        FluidPropagator.resetAffectedFluidNetworks(level, worldPosition, side.getOpposite());
    if (!hasReachedValidEndpoint(level, start, pull)) {
        pipeGraph.computeIfAbsent(worldPosition, $ -> Pair.of(0, new IdentityHashMap<>())).getSecond().put(side, pull);
        pipeGraph.computeIfAbsent(start.getConnectedPos(), $ -> Pair.of(1, new IdentityHashMap<>())).getSecond().put(side.getOpposite(), !pull);
        List<Pair<Integer, BlockPos>> frontier = new ArrayList<>();
        Set<BlockPos> visited = new HashSet<>();
        int maxDistance = FluidPropagator.getPumpRange();
        frontier.add(Pair.of(1, start.getConnectedPos()));
        while (!frontier.isEmpty()) {
            Pair<Integer, BlockPos> entry = frontier.remove(0);
            int distance = entry.getFirst();
            BlockPos currentPos = entry.getSecond();
            if (!level.isAreaLoaded(currentPos, 0))
                continue;
            if (visited.contains(currentPos))
                continue;
            visited.add(currentPos);
            BlockState currentState = level.getBlockState(currentPos);
            FluidTransportBehaviour pipe = FluidPropagator.getPipe(level, currentPos);
            if (pipe == null)
                continue;
            for (Direction face : FluidPropagator.getPipeConnections(currentState, pipe)) {
                BlockFace blockFace = new BlockFace(currentPos, face);
                BlockPos connectedPos = blockFace.getConnectedPos();
                if (!level.isAreaLoaded(connectedPos, 0))
                    continue;
                if (blockFace.isEquivalent(start))
                    continue;
                if (hasReachedValidEndpoint(level, blockFace, pull)) {
                    pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())).getSecond().put(face, pull);
                    targets.add(blockFace);
                    continue;
                }
                FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, connectedPos);
                if (pipeBehaviour == null)
                    continue;
                if (pipeBehaviour instanceof PumpFluidTransferBehaviour)
                    continue;
                if (visited.contains(connectedPos))
                    continue;
                if (distance + 1 >= maxDistance) {
                    pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())).getSecond().put(face, pull);
                    targets.add(blockFace);
                    continue;
                }
                pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())).getSecond().put(face, pull);
                pipeGraph.computeIfAbsent(connectedPos, $ -> Pair.of(distance + 1, new IdentityHashMap<>())).getSecond().put(face.getOpposite(), !pull);
                frontier.add(Pair.of(distance + 1, connectedPos));
            }
        }
    }
    // DFS
    Map<Integer, Set<BlockFace>> validFaces = new HashMap<>();
    searchForEndpointRecursively(pipeGraph, targets, validFaces, new BlockFace(start.getPos(), start.getOppositeFace()), pull);
    float pressure = Math.abs(getSpeed());
    for (Set<BlockFace> set : validFaces.values()) {
        int parallelBranches = set.size();
        for (BlockFace face : set) {
            BlockPos pipePos = face.getPos();
            Direction pipeSide = face.getFace();
            if (pipePos.equals(worldPosition))
                continue;
            boolean inbound = pipeGraph.get(pipePos).getSecond().get(pipeSide);
            FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, pipePos);
            if (pipeBehaviour == null)
                continue;
            pipeBehaviour.addPressure(pipeSide, inbound, pressure / parallelBranches);
        }
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) IdentityHashMap(java.util.IdentityHashMap) BlockFace(com.simibubi.create.foundation.utility.BlockFace) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) Direction(net.minecraft.core.Direction) BlockState(net.minecraft.world.level.block.state.BlockState) BlockPos(net.minecraft.core.BlockPos) MutableBoolean(org.apache.commons.lang3.mutable.MutableBoolean) HashSet(java.util.HashSet) Pair(com.simibubi.create.foundation.utility.Pair)

Example 3 with BlockFace

use of com.simibubi.create.foundation.utility.BlockFace in project Create by Creators-of-Create.

the class Contraption method onEntityCreated.

public void onEntityCreated(AbstractContraptionEntity entity) {
    this.entity = entity;
    // Create subcontraptions
    for (BlockFace blockFace : pendingSubContraptions) {
        Direction face = blockFace.getFace();
        StabilizedContraption subContraption = new StabilizedContraption(face);
        Level world = entity.level;
        BlockPos pos = blockFace.getPos();
        try {
            if (!subContraption.assemble(world, pos))
                continue;
        } catch (AssemblyException e) {
            continue;
        }
        subContraption.removeBlocksFromWorld(world, BlockPos.ZERO);
        OrientedContraptionEntity movedContraption = OrientedContraptionEntity.create(world, subContraption, face);
        BlockPos anchor = blockFace.getConnectedPos();
        movedContraption.setPos(anchor.getX() + .5f, anchor.getY(), anchor.getZ() + .5f);
        world.addFreshEntity(movedContraption);
        stabilizedSubContraptions.put(movedContraption.getUUID(), new BlockFace(toLocalPos(pos), face));
    }
    // Gather itemhandlers of mounted storage
    List<IItemHandlerModifiable> list = storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList());
    inventory = new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
    List<IFluidHandler> fluidHandlers = fluidStorage.values().stream().map(MountedFluidStorage::getFluidHandler).collect(Collectors.toList());
    fluidInventory = new CombinedTankWrapper(Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
    gatherBBsOffThread();
}
Also used : BlockFace(com.simibubi.create.foundation.utility.BlockFace) Direction(net.minecraft.core.Direction) StabilizedContraption(com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption) IFluidHandler(net.minecraftforge.fluids.capability.IFluidHandler) IItemHandlerModifiable(net.minecraftforge.items.IItemHandlerModifiable) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) BlockPos(net.minecraft.core.BlockPos) CombinedTankWrapper(com.simibubi.create.foundation.fluid.CombinedTankWrapper)

Example 4 with BlockFace

use of com.simibubi.create.foundation.utility.BlockFace in project Create by Creators-of-Create.

the class Contraption method moveBearing.

private void moveBearing(BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
    Direction facing = state.getValue(MechanicalBearingBlock.FACING);
    if (!canBeStabilized(facing, pos.subtract(anchor))) {
        BlockPos offset = pos.relative(facing);
        if (!visited.contains(offset))
            frontier.add(offset);
        return;
    }
    pendingSubContraptions.add(new BlockFace(pos, facing));
}
Also used : BlockFace(com.simibubi.create.foundation.utility.BlockFace) BlockPos(net.minecraft.core.BlockPos) Direction(net.minecraft.core.Direction)

Example 5 with BlockFace

use of com.simibubi.create.foundation.utility.BlockFace in project Create by Creators-of-Create.

the class FunnelTileEntity method addBehaviours.

@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
    invManipulation = new InvManipulationBehaviour(this, (w, p, s) -> new BlockFace(p, AbstractFunnelBlock.getFunnelFacing(s).getOpposite()));
    behaviours.add(invManipulation);
    filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning());
    filtering.showCountWhen(this::supportsAmountOnFilter);
    filtering.onlyActiveWhen(this::supportsFiltering);
    behaviours.add(filtering);
    behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput).setInsertionHandler(this::handleDirectBeltInput));
}
Also used : InstancedRenderDispatcher(com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher) AllPackets(com.simibubi.create.foundation.networking.AllPackets) IHaveHoveringInformation(com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation) VecHelper(com.simibubi.create.foundation.utility.VecHelper) AABB(net.minecraft.world.phys.AABB) InvManipulationBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour) Direction(net.minecraft.core.Direction) BlockState(net.minecraft.world.level.block.state.BlockState) BeltHelper(com.simibubi.create.content.contraptions.relays.belt.BeltHelper) FilteringBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour) Dist(net.minecraftforge.api.distmarker.Dist) SmartTileEntity(com.simibubi.create.foundation.tileEntity.SmartTileEntity) InterpolatedChasingValue(com.simibubi.create.foundation.utility.animation.InterpolatedChasingValue) AllConfigs(com.simibubi.create.foundation.config.AllConfigs) BlockFace(com.simibubi.create.foundation.utility.BlockFace) WeakReference(java.lang.ref.WeakReference) AllBlocks(com.simibubi.create.AllBlocks) BlockStateProperties(net.minecraft.world.level.block.state.properties.BlockStateProperties) TileEntityBehaviour(com.simibubi.create.foundation.tileEntity.TileEntityBehaviour) DistExecutor(net.minecraftforge.fml.DistExecutor) BeltTileEntity(com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity) List(java.util.List) CompoundTag(net.minecraft.nbt.CompoundTag) BlockPos(net.minecraft.core.BlockPos) ItemEntity(net.minecraft.world.entity.item.ItemEntity) BlockEntityType(net.minecraft.world.level.block.entity.BlockEntityType) Vec3(net.minecraft.world.phys.Vec3) Shape(com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape) TransportedItemStack(com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack) FunnelFlapPacket(com.simibubi.create.content.logistics.packet.FunnelFlapPacket) ItemStack(net.minecraft.world.item.ItemStack) DirectBeltInputBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour) AllSoundEvents(com.simibubi.create.AllSoundEvents) FilteringBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour) DirectBeltInputBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour) BlockFace(com.simibubi.create.foundation.utility.BlockFace) InvManipulationBehaviour(com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour)

Aggregations

BlockFace (com.simibubi.create.foundation.utility.BlockFace)11 BlockPos (net.minecraft.core.BlockPos)7 Direction (net.minecraft.core.Direction)6 Pair (com.simibubi.create.foundation.utility.Pair)3 ArrayList (java.util.ArrayList)3 BlockState (net.minecraft.world.level.block.state.BlockState)3 SmartTileEntity (com.simibubi.create.foundation.tileEntity.SmartTileEntity)2 TileEntityBehaviour (com.simibubi.create.foundation.tileEntity.TileEntityBehaviour)2 DirectBeltInputBehaviour (com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 IdentityHashMap (java.util.IdentityHashMap)2 List (java.util.List)2 CompoundTag (net.minecraft.nbt.CompoundTag)2 ItemStack (net.minecraft.world.item.ItemStack)2 BlockEntity (net.minecraft.world.level.block.entity.BlockEntity)2 BlockEntityType (net.minecraft.world.level.block.entity.BlockEntityType)2 IFluidHandler (net.minecraftforge.fluids.capability.IFluidHandler)2 InstancedRenderDispatcher (com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher)1 AllBlocks (com.simibubi.create.AllBlocks)1