Search in sources :

Example 1 with Pair

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

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

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

the class PonderScene method rayTraceScene.

public Pair<ItemStack, BlockPos> rayTraceScene(Vec3 from, Vec3 to) {
    MutableObject<Pair<WorldSectionElement, BlockPos>> nearestHit = new MutableObject<>();
    MutableDouble bestDistance = new MutableDouble(0);
    forEach(WorldSectionElement.class, wse -> {
        wse.resetSelectedBlock();
        if (!wse.isVisible())
            return;
        Pair<Vec3, BlockPos> rayTrace = wse.rayTrace(world, from, to);
        if (rayTrace == null)
            return;
        double distanceTo = rayTrace.getFirst().distanceTo(from);
        if (nearestHit.getValue() != null && distanceTo >= bestDistance.getValue())
            return;
        nearestHit.setValue(Pair.of(wse, rayTrace.getSecond()));
        bestDistance.setValue(distanceTo);
    });
    if (nearestHit.getValue() == null)
        return Pair.of(ItemStack.EMPTY, null);
    BlockPos selectedPos = nearestHit.getValue().getSecond();
    BlockPos origin = new BlockPos(basePlateOffsetX, 0, basePlateOffsetZ);
    if (!world.getBounds().isInside(selectedPos))
        return Pair.of(ItemStack.EMPTY, null);
    if (BoundingBox.fromCorners(origin, origin.offset(new Vec3i(basePlateSize - 1, 0, basePlateSize - 1))).isInside(selectedPos)) {
        if (PonderIndex.editingModeActive())
            nearestHit.getValue().getFirst().selectBlock(selectedPos);
        return Pair.of(ItemStack.EMPTY, selectedPos);
    }
    nearestHit.getValue().getFirst().selectBlock(selectedPos);
    BlockState blockState = world.getBlockState(selectedPos);
    ItemStack pickBlock = blockState.getCloneItemStack(new BlockHitResult(VecHelper.getCenterOf(selectedPos), Direction.UP, selectedPos, true), world, selectedPos, Minecraft.getInstance().player);
    return Pair.of(pickBlock, selectedPos);
}
Also used : Vec3i(net.minecraft.core.Vec3i) BlockState(net.minecraft.world.level.block.state.BlockState) MutableDouble(org.apache.commons.lang3.mutable.MutableDouble) Vec3(net.minecraft.world.phys.Vec3) BlockPos(net.minecraft.core.BlockPos) ItemStack(net.minecraft.world.item.ItemStack) BlockHitResult(net.minecraft.world.phys.BlockHitResult) Pair(com.simibubi.create.foundation.utility.Pair) MutableObject(org.apache.commons.lang3.mutable.MutableObject)

Example 4 with Pair

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

the class CloneCommand method cloneGlue.

private static int cloneGlue(BoundingBox sourceArea, ServerLevel world, BlockPos diffToTarget) {
    int gluePastes = 0;
    List<SuperGlueEntity> glue = world.getEntitiesOfClass(SuperGlueEntity.class, AABB.of(sourceArea));
    List<Pair<BlockPos, Direction>> newGlue = Lists.newArrayList();
    for (SuperGlueEntity g : glue) {
        BlockPos pos = g.getHangingPosition();
        Direction direction = g.getFacingDirection();
        newGlue.add(Pair.of(pos.offset(diffToTarget), direction));
    }
    for (Pair<BlockPos, Direction> p : newGlue) {
        SuperGlueEntity g = new SuperGlueEntity(world, p.getFirst(), p.getSecond());
        if (g.onValidSurface()) {
            world.addFreshEntity(g);
            gluePastes++;
        }
    }
    return gluePastes;
}
Also used : SuperGlueEntity(com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity) BlockPos(net.minecraft.core.BlockPos) Direction(net.minecraft.core.Direction) Pair(com.simibubi.create.foundation.utility.Pair)

Example 5 with Pair

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

the class BasinCategory method setRecipe.

@Override
public void setRecipe(IRecipeLayout recipeLayout, BasinRecipe recipe, IIngredients iingredients) {
    IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
    IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks();
    NonNullList<FluidIngredient> fluidIngredients = recipe.getFluidIngredients();
    List<Pair<Ingredient, MutableInt>> ingredients = ItemHelper.condenseIngredients(recipe.getIngredients());
    List<ItemStack> itemOutputs = recipe.getRollableResultsAsItemStacks();
    NonNullList<FluidStack> fluidOutputs = recipe.getFluidResults();
    int size = ingredients.size() + fluidIngredients.size();
    int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0;
    int yOffset = 0;
    int i;
    for (i = 0; i < ingredients.size(); i++) {
        itemStacks.init(i, true, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19 + yOffset);
        List<ItemStack> stacks = new ArrayList<>();
        Pair<Ingredient, MutableInt> pair = ingredients.get(i);
        Ingredient ingredient = pair.getFirst();
        MutableInt amount = pair.getSecond();
        for (ItemStack itemStack : ingredient.getItems()) {
            ItemStack stack = itemStack.copy();
            stack.setCount(amount.getValue());
            stacks.add(stack);
        }
        itemStacks.set(i, stacks);
    }
    int j;
    for (j = 0; j < fluidIngredients.size(); j++) {
        int i2 = i + j;
        fluidStacks.init(j, true, 17 + xOffset + (i2 % 3) * 19, 51 - (i2 / 3) * 19 + yOffset);
        List<FluidStack> stacks = fluidIngredients.get(j).getMatchingFluidStacks();
        fluidStacks.set(j, withImprovedVisibility(stacks));
    }
    int outSize = fluidOutputs.size() + recipe.getRollableResults().size();
    int outputIndex = 0;
    if (!itemOutputs.isEmpty())
        addStochasticTooltip(itemStacks, recipe.getRollableResults(), i);
    for (; outputIndex < outSize; outputIndex++) {
        int xPosition = 141 - (outSize % 2 != 0 && outputIndex == outSize - 1 ? 0 : outputIndex % 2 == 0 ? 10 : -9);
        int yPosition = -19 * (outputIndex / 2) + 50 + yOffset;
        if (itemOutputs.size() > outputIndex) {
            itemStacks.init(i, false, xPosition, yPosition + yOffset);
            itemStacks.set(i, itemOutputs.get(outputIndex));
            i++;
        } else {
            fluidStacks.init(j, false, xPosition + 1, yPosition + 1 + yOffset);
            fluidStacks.set(j, withImprovedVisibility(fluidOutputs.get(outputIndex - itemOutputs.size())));
            j++;
        }
    }
    addFluidTooltip(fluidStacks, fluidIngredients, fluidOutputs);
    HeatCondition requiredHeat = recipe.getRequiredHeat();
    if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) {
        itemStacks.init(i, true, 133, 80);
        itemStacks.set(i, AllBlocks.BLAZE_BURNER.asStack());
        i++;
    }
    if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) {
        itemStacks.init(i, true, 152, 80);
        itemStacks.set(i, AllItems.BLAZE_CAKE.asStack());
        i++;
    }
}
Also used : FluidStack(net.minecraftforge.fluids.FluidStack) IGuiFluidStackGroup(mezz.jei.api.gui.ingredient.IGuiFluidStackGroup) IGuiItemStackGroup(mezz.jei.api.gui.ingredient.IGuiItemStackGroup) ArrayList(java.util.ArrayList) HeatCondition(com.simibubi.create.content.contraptions.processing.HeatCondition) FluidIngredient(com.simibubi.create.foundation.fluid.FluidIngredient) Ingredient(net.minecraft.world.item.crafting.Ingredient) FluidIngredient(com.simibubi.create.foundation.fluid.FluidIngredient) MutableInt(org.apache.commons.lang3.mutable.MutableInt) ItemStack(net.minecraft.world.item.ItemStack) Pair(com.simibubi.create.foundation.utility.Pair)

Aggregations

Pair (com.simibubi.create.foundation.utility.Pair)9 ArrayList (java.util.ArrayList)6 BlockPos (net.minecraft.core.BlockPos)5 Direction (net.minecraft.core.Direction)5 BlockState (net.minecraft.world.level.block.state.BlockState)4 BlockFace (com.simibubi.create.foundation.utility.BlockFace)3 HashSet (java.util.HashSet)3 ItemStack (net.minecraft.world.item.ItemStack)3 HeatCondition (com.simibubi.create.content.contraptions.processing.HeatCondition)2 AllGuiTextures (com.simibubi.create.foundation.gui.AllGuiTextures)2 HashMap (java.util.HashMap)2 IdentityHashMap (java.util.IdentityHashMap)2 List (java.util.List)2 Set (java.util.Set)2 CompoundTag (net.minecraft.nbt.CompoundTag)2 BlockEntity (net.minecraft.world.level.block.entity.BlockEntity)2 PoseStack (com.mojang.blaze3d.vertex.PoseStack)1 KineticTileEntity (com.simibubi.create.content.contraptions.base.KineticTileEntity)1 SuperGlueEntity (com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity)1 Flow (com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow)1