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