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;
}
}
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);
}
}
}
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);
}
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;
}
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++;
}
}
Aggregations