Mekanism-tilera-Edition/src/main/java/mekanism/api/gas/GasTransmission.java
2023-01-22 17:18:34 +01:00

194 lines
6.6 KiB
Java

package mekanism.api.gas;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import mekanism.api.Coord4D;
import mekanism.api.transmitters.ITransmitterTile;
import mekanism.api.transmitters.TransmissionType;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
/**
* A handy class containing several utilities for efficient gas transfer.
* @author AidanBrady
*
*/
public final class GasTransmission {
public static IGasHandler[] getConnectedAcceptors(
TileEntity tileEntity, Collection<ForgeDirection> sides
) {
IGasHandler[] acceptors
= new IGasHandler[] { null, null, null, null, null, null };
for (ForgeDirection orientation : sides) {
TileEntity acceptor = Coord4D.get(tileEntity)
.getFromSide(orientation)
.getTileEntity(tileEntity.getWorldObj());
if (acceptor instanceof IGasHandler) {
acceptors[orientation.ordinal()] = (IGasHandler) acceptor;
}
}
return acceptors;
}
/**
* Gets all the acceptors around a tile entity.
* @param tileEntity - center tile entity
* @return array of IGasAcceptors
*/
public static IGasHandler[] getConnectedAcceptors(TileEntity tileEntity) {
return getConnectedAcceptors(
tileEntity, Arrays.asList(ForgeDirection.VALID_DIRECTIONS)
);
}
/**
* Gets all the tube connections around a tile entity.
* @param tileEntity - center tile entity
* @return array of ITubeConnections
*/
public static ITubeConnection[] getConnections(TileEntity tileEntity) {
ITubeConnection[] connections
= new ITubeConnection[] { null, null, null, null, null, null };
for (ForgeDirection orientation : ForgeDirection.VALID_DIRECTIONS) {
TileEntity connection = Coord4D.get(tileEntity)
.getFromSide(orientation)
.getTileEntity(tileEntity.getWorldObj());
if (canConnect(connection, orientation)) {
connections[orientation.ordinal()] = (ITubeConnection) connection;
}
}
return connections;
}
/**
* Whether or not a TileEntity can connect to a specified tile on a specified side.
* @param tileEntity - TileEntity to attempt connection to
* @param side - side to attempt connection on
* @return if this tile and side are connectable
*/
public static boolean canConnect(TileEntity tileEntity, ForgeDirection side) {
if (tileEntity instanceof ITubeConnection
&& (!(tileEntity instanceof ITransmitterTile)
|| TransmissionType.checkTransmissionType(
((ITransmitterTile) tileEntity).getTransmitter(), TransmissionType.GAS
))) {
if (((ITubeConnection) tileEntity).canTubeConnect(side.getOpposite())) {
return true;
}
}
return false;
}
/**
* Removes a specified amount of gas from an IGasItem.
* @param itemStack - ItemStack of the IGasItem
* @param type - type of gas to remove from the IGasItem, null if it doesn't matter
* @param amount - amount of gas to remove from the ItemStack
* @return the GasStack removed by the IGasItem
*/
public static GasStack removeGas(ItemStack itemStack, Gas type, int amount) {
if (itemStack != null && itemStack.getItem() instanceof IGasItem) {
IGasItem item = (IGasItem) itemStack.getItem();
if (type != null && item.getGas(itemStack) != null
&& item.getGas(itemStack).getGas() != type
|| !item.canProvideGas(itemStack, type)) {
return null;
}
return item.removeGas(itemStack, amount);
}
return null;
}
/**
* Adds a specified amount of gas to an IGasItem.
* @param itemStack - ItemStack of the IGasItem
* @param stack - stack to add to the IGasItem
* @return amount of gas accepted by the IGasItem
*/
public static int addGas(ItemStack itemStack, GasStack stack) {
if (itemStack != null && itemStack.getItem() instanceof IGasItem
&& ((IGasItem) itemStack.getItem())
.canReceiveGas(itemStack, stack.getGas())) {
return ((IGasItem) itemStack.getItem()).addGas(itemStack, stack.copy());
}
return 0;
}
/**
* Emits gas from a central block by splitting the received stack among the sides
* given.
* @param stack - the stack to output
* @param from - the TileEntity to output from
* @param sides - the list of sides to output from
* @return the amount of gas emitted
*/
public static int
emit(GasStack stack, TileEntity from, Collection<ForgeDirection> sides) {
if (stack == null) {
return 0;
}
List<IGasHandler> availableAcceptors = new ArrayList<IGasHandler>();
IGasHandler[] possibleAcceptors = getConnectedAcceptors(from, sides);
for (int i = 0; i < possibleAcceptors.length; i++) {
IGasHandler handler = possibleAcceptors[i];
if (handler != null
&& handler.canReceiveGas(
ForgeDirection.getOrientation(i).getOpposite(), stack.getGas()
)) {
availableAcceptors.add(handler);
}
}
Collections.shuffle(availableAcceptors);
int toSend = stack.amount;
int prevSending = toSend;
if (!availableAcceptors.isEmpty()) {
int divider = availableAcceptors.size();
int remaining = toSend % divider;
int sending = (toSend - remaining) / divider;
for (IGasHandler acceptor : availableAcceptors) {
int currentSending = sending;
if (remaining > 0) {
currentSending++;
remaining--;
}
ForgeDirection dir
= ForgeDirection
.getOrientation(
Arrays.asList(possibleAcceptors).indexOf(acceptor)
)
.getOpposite();
toSend -= acceptor.receiveGas(
dir, new GasStack(stack.getGas(), currentSending), true
);
}
}
return prevSending - toSend;
}
}