Merge pull request #86 from GTNewHorizons/blockingfix

Blockingfix
This commit is contained in:
Yang Xizhi authored and GitHub committed 2023-02-23 20:40:23 +08:00
commit 9615e1cbf0
4 files changed
+315 -76

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
dependencies {
compile('com.github.GTNewHorizons:NotEnoughItems:2.3.32-GTNH:dev')
compile('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-158-GTNH:dev')
compile('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-160-GTNH:dev')
compile('curse.maven:cofh-core-69162:2388751')
compile('com.github.GTNewHorizons:waila:1.5.22:dev')
compileOnly('com.github.GTNewHorizons:ExtraCells2:2.5.32:dev') { transitive = false }
@@ -28,7 +28,7 @@ import cpw.mods.fml.common.network.NetworkRegistry;
modid = FluidCraft.MODID,
version = FluidCraft.VERSION,
name = FluidCraft.MODNAME,
dependencies = "required-after:appliedenergistics2;required-after:CoFHCore;after:waila;after:thaumicenergistics;after:ae2wct")
dependencies = "required-after:appliedenergistics2;required-after:CoFHCore;required-after:Baubles;after:waila;after:thaumicenergistics;after:ae2wct")
public class FluidCraft {
public static final String MODID = "GRADLETOKEN_MODID";
@@ -1,9 +1,8 @@
package com.glodblock.github.inventory;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import javax.annotation.Nullable;
@@ -16,9 +15,14 @@ import net.minecraftforge.fluids.IFluidHandler;
import appeng.api.config.FuzzyMode;
import appeng.api.config.InsertionMode;
import appeng.api.parts.IPart;
import appeng.helpers.DualityInterface;
import appeng.helpers.IInterfaceHost;
import appeng.me.GridAccessException;
import appeng.me.helpers.AENetworkProxy;
import appeng.parts.p2p.PartP2PLiquids;
import appeng.tile.misc.TileInterface;
import appeng.tile.networking.TileCableBus;
import appeng.util.InventoryAdaptor;
import appeng.util.inv.IInventoryDestination;
import appeng.util.inv.ItemSlot;
@@ -34,24 +38,47 @@ import com.glodblock.github.util.BlockPos;
import com.glodblock.github.util.ModAndClassUtil;
import com.glodblock.github.util.Util;
import crazypants.enderio.conduit.item.IItemConduit;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.MetaPipeEntity;
public class FluidConvertingInventoryAdaptor extends InventoryAdaptor {
// facing is the target TE direction
// |T|-facing->|I|
public FluidConvertingInventoryAdaptor(@Nullable InventoryAdaptor invItems, @Nullable IFluidHandler invFluids,
ForgeDirection facing, BlockPos pos, boolean isOnmi, Object eioConduct) {
ForgeDirection facing, BlockPos pos, boolean isOnmi) {
this.invItems = invItems;
this.invFluids = invFluids;
this.side = facing;
this.posInterface = pos;
this.eioDuct = eioConduct;
this.onmi = isOnmi;
this.selfInterface = getInterfaceTE(pos.getTileEntity(), facing.getOpposite());
}
private final InventoryAdaptor invItems;
private final IFluidHandler invFluids;
private final ForgeDirection side;
private final BlockPos posInterface;
private final Object eioDuct;
@Nullable
private final IInterfaceHost selfInterface;
private final boolean onmi;
private static Method eioTypeCheck;
private static Class<?> conduitClazz;
static {
if (ModAndClassUtil.EIO) {
try {
conduitClazz = Class.forName("crazypants.enderio.conduit.TileConduitBundle");
eioTypeCheck = conduitClazz.getDeclaredMethod("getConduit", Class.class);
} catch (ClassNotFoundException | NoSuchMethodException e) {
eioTypeCheck = null;
}
} else {
eioTypeCheck = null;
}
}
public static InventoryAdaptor wrap(TileEntity capProvider, ForgeDirection face) {
// sometimes i wish 1.7.10 has cap system.
@@ -69,31 +96,69 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor {
if (inter instanceof TileInterface) {
onmi = ((TileInterface) inter).getTargets().size() > 1;
}
Object conduct = null;
if (ModAndClassUtil.COFH && capProvider instanceof IItemDuct) {
conduct = capProvider;
}
return new FluidConvertingInventoryAdaptor(item, fluid, face, new BlockPos(inter), onmi, conduct);
return new FluidConvertingInventoryAdaptor(item, fluid, face, new BlockPos(inter), onmi);
}
public ItemStack addItems(ItemStack toBeAdded, InsertionMode insertionMode) {
FluidStack fluid = Util.getFluidFromVirtual(toBeAdded);
if (fluid != null) {
if (invFluids != null) {
if (invFluids.canFill(side, fluid.getFluid())) {
int filled = invFluids.fill(side, fluid, true);
if (filled > 0) {
fluid.amount -= filled;
return ItemFluidPacket.newStack(fluid);
}
}
if (!this.onmi) {
if (!checkValidSide(
this.posInterface.getOffSet(this.side.getOpposite()).getTileEntity(),
this.side.getOpposite())) {
return toBeAdded;
}
if (fluid != null) {
int filled = fillSideFluid(fluid, this.invFluids, this.side, true);
fluid.amount -= filled;
return ItemFluidPacket.newStack(fluid);
} else {
ItemStack notFilled = fillSideItem(toBeAdded, this.invItems, insertionMode, true);
if (notFilled != null) {
// Fill EIO Conduit at last.
return fillEIOConduit(
notFilled,
this.posInterface.getOffSet(this.side.getOpposite()).getTileEntity(),
this.side);
}
return null;
}
} else {
if (fluid != null) {
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if (fluid.amount <= 0) {
return null;
}
if (!checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)) {
continue;
}
int filled = fillSideFluid(fluid, getSideFluid(dir), dir.getOpposite(), true);
fluid.amount -= filled;
}
return ItemFluidPacket.newStack(fluid);
} else {
ItemStack item = toBeAdded.copy();
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if (item == null || item.stackSize <= 0) {
return null;
}
if (!checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)) {
continue;
}
item = fillSideItem(item, getSideItem(dir), insertionMode, true);
}
// Fill EIO Conduit at last.
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if (item == null || item.stackSize <= 0) {
return null;
}
if (!checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)) {
continue;
}
item = fillEIOConduit(item, this.posInterface.getOffSet(dir).getTileEntity(), dir.getOpposite());
}
return item;
}
return toBeAdded;
}
if (eioDuct != null) {
return ((IItemDuct) eioDuct).insertItem(side, toBeAdded);
}
return invItems != null ? invItems.addItems(toBeAdded, insertionMode) : toBeAdded;
}
@Override
@@ -109,35 +174,56 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor {
@Override
public ItemStack simulateAdd(ItemStack toBeSimulated, InsertionMode insertionMode) {
FluidStack fluid = Util.getFluidFromVirtual(toBeSimulated);
if (fluid != null) {
if (onmi) {
boolean sus = false;
for (ForgeDirection dir : ForgeDirection.values()) {
TileEntity te = posInterface.getOffSet(dir).getTileEntity();
if (te instanceof IFluidHandler) {
int filled = ((IFluidHandler) te).fill(dir.getOpposite(), fluid, false);
if (filled > 0) {
sus = true;
break;
}
if (!this.onmi) {
if (!checkValidSide(
this.posInterface.getOffSet(this.side.getOpposite()).getTileEntity(),
this.side.getOpposite())) {
return toBeSimulated;
}
if (fluid != null) {
int filled = fillSideFluid(fluid, this.invFluids, this.side, false);
fluid.amount -= filled;
return ItemFluidPacket.newStack(fluid);
} else {
// Assert EIO conduit can hold all item, as it is the origin practice in AE2
if (isConduit(this.posInterface.getOffSet(this.side.getOpposite()).getTileEntity())) {
return null;
} else {
return fillSideItem(toBeSimulated, this.invItems, insertionMode, false);
}
}
} else {
// In onmi mode, fluid/item only need to be partly inserted.
boolean sus = false;
if (fluid != null) {
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if (!checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)) {
continue;
}
int filled = fillSideFluid(fluid, getSideFluid(dir), dir.getOpposite(), false);
if (filled > 0) {
sus = true;
break;
}
}
return sus ? null : toBeSimulated;
}
if (invFluids != null) {
int filled = invFluids.fill(side, fluid, false);
if (filled > 0) {
fluid.amount -= filled;
return ItemFluidPacket.newStack(fluid);
} else {
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if (!checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)) {
continue;
}
// Assert EIO conduit can hold all item, as it is the origin practice in AE2
if (isConduit(this.posInterface.getOffSet(dir).getTileEntity())) {
return null;
}
ItemStack notFilled = fillSideItem(toBeSimulated, getSideItem(dir), insertionMode, false);
if (notFilled == null || notFilled.stackSize < toBeSimulated.stackSize) {
sus = true;
break;
}
}
}
return toBeSimulated;
return sus ? null : toBeSimulated;
}
// Assert EIO conduct can hold all item, as it is the origin practice in AE2
if (eioDuct != null) {
return null;
}
return invItems != null ? invItems.simulateAdd(toBeSimulated, insertionMode) : toBeSimulated;
}
@Override
@@ -164,15 +250,123 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor {
@Override
public boolean containsItems() {
if (invFluids == null && invItems == null) {
// If this entity doesn't have fluid or item inventory, we just view it as full of things.
return true;
if (!this.onmi) {
// If there is no fluid tank or item inventory, it shouldn't send stuff here.
return checkItemFluids(this.invFluids, this.invItems, this.side) > 0;
}
if (invFluids != null && invFluids.getTankInfo(this.side) != null) {
boolean anyValid = false;
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
// Avoid sending stuff into itself me network
if (checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)
&& !isItemConduit(this.posInterface.getOffSet(dir).getTileEntity())) {
final int result = checkItemFluids(this.getSideFluid(dir), this.getSideItem(dir), dir.getOpposite());
if (result == 1) {
return true;
}
if (result != 2) {
anyValid = true;
}
}
}
// Same here. if there is no fluid tank or item inventory existed, it shouldn't send stuff here.
return !anyValid;
}
public boolean hasSlots() {
return (invFluids != null && invFluids.getTankInfo(side).length > 0) || (invItems != null);
}
@Override
public Iterator<ItemSlot> iterator() {
return new SlotIterator(
invFluids != null ? invFluids.getTankInfo(side) : new FluidTankInfo[0],
invItems != null ? invItems.iterator() : Collections.emptyIterator());
}
private IFluidHandler getSideFluid(ForgeDirection direction) {
TileEntity te = this.posInterface.getOffSet(direction).getTileEntity();
if (te instanceof IFluidHandler) {
return (IFluidHandler) te;
}
return null;
}
private int fillSideFluid(FluidStack fluid, IFluidHandler tank, ForgeDirection direction, boolean doFill) {
if (tank != null) {
return tank.fill(direction, fluid, doFill);
}
return 0;
}
// EIO conduit isn't considered here
private ItemStack fillSideItem(ItemStack item, InventoryAdaptor inv, InsertionMode mode, boolean doFill) {
if (inv != null) {
if (doFill) {
return inv.addItems(item, mode);
} else {
return inv.simulateAdd(item, mode);
}
}
return item;
}
private int gtMachineCircuitCheck(InventoryAdaptor ad) {
if (ad == null) {
return 0;
}
for (ItemSlot i : ad) {
ItemStack is = i.getItemStack();
if (is == null || Objects.requireNonNull(is.getItem()).getUnlocalizedName().equals("gt.integrated_circuit"))
continue;
return 1;
}
return 0;
}
private boolean isGTMachine(Object o) {
return ModAndClassUtil.GT5 && o instanceof TileEntity
&& ((TileEntity) o).getBlockType().getUnlocalizedName().equals("gt.blockmachines");
}
private boolean isItemConduit(TileEntity te) {
if (ModAndClassUtil.EIO && conduitClazz.isInstance(te)) {
try {
return eioTypeCheck.invoke(te, IItemConduit.class) != null;
} catch (InvocationTargetException | IllegalAccessException e) {
return false;
}
}
return false;
}
private boolean isConduit(TileEntity te) {
return ModAndClassUtil.EIO && te instanceof IItemDuct;
}
private ItemStack fillEIOConduit(ItemStack item, TileEntity te, ForgeDirection direction) {
if (isConduit(te)) {
return ((IItemDuct) te).insertItem(direction, item);
}
return item;
}
private InventoryAdaptor getSideItem(ForgeDirection direction) {
TileEntity te = this.posInterface.getOffSet(direction).getTileEntity();
return InventoryAdaptor.getAdaptor(te, direction.getOpposite());
}
// 0 - It is empty
// 1 - It contains item/fluid
// 2 - It doesn't exist
private int checkItemFluids(IFluidHandler tank, InventoryAdaptor inv, ForgeDirection direction) {
if (tank == null && inv == null) {
return 2;
}
if (tank != null && tank.getTankInfo(direction) != null) {
List<FluidTankInfo[]> tankInfos = new LinkedList<>();
if (Util.getPart(invFluids, this.side) instanceof PartP2PLiquids) {
if (Util.getPart(tank, direction) instanceof PartP2PLiquids) {
// read other ends of p2p for blocking mode
PartP2PLiquids invFluidsP2P = (PartP2PLiquids) Util.getPart(invFluids, this.side);
PartP2PLiquids invFluidsP2P = (PartP2PLiquids) Util.getPart(tank, direction);
try {
Iterator<PartP2PLiquids> it = invFluidsP2P.getOutputs().iterator();
boolean checkedInput = false;
@@ -191,35 +385,72 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor {
}
} catch (GridAccessException ignore) {}
} else {
tankInfos.add(invFluids.getTankInfo(this.side));
tankInfos.add(tank.getTankInfo(direction));
}
boolean hasTank = false;
for (FluidTankInfo[] tankInfoArray : tankInfos) {
for (FluidTankInfo tank : tankInfoArray) {
for (FluidTankInfo tankInfo : tankInfoArray) {
hasTank = true;
FluidStack fluid = tank.fluid;
FluidStack fluid = tankInfo.fluid;
if (fluid != null && fluid.amount > 0) {
return true;
return 1;
}
}
}
if (!hasTank && invItems == null) {
// If this entity doesn't have fluid or item inventory, we just view it as full of things.
if (!hasTank && inv == null) {
return 2;
}
}
if (isGTMachine(tank)) {
return gtMachineCircuitCheck(inv);
}
return inv != null && inv.containsItems() ? 1 : 0;
}
private boolean checkValidSide(TileEntity te, ForgeDirection direction) {
if (isGTMachine(te)) {
return checkGTPipeConnection(te, direction.getOpposite());
}
return isDifferentGrid(getInterfaceTE(te, direction.getOpposite()));
}
private boolean checkGTPipeConnection(TileEntity te, ForgeDirection direction) {
if (te instanceof IGregTechTileEntity) {
IMetaTileEntity mte = ((IGregTechTileEntity) te).getMetaTileEntity();
if (mte instanceof MetaPipeEntity) {
return ((MetaPipeEntity) mte).isConnectedAtSide(direction.ordinal());
}
}
return true;
}
private static IInterfaceHost getInterfaceTE(TileEntity te, ForgeDirection face) {
if (te instanceof IInterfaceHost) {
return (IInterfaceHost) te;
} else if (te instanceof TileCableBus) {
IPart part = ((TileCableBus) te).getPart(face);
if (part instanceof IInterfaceHost) {
return (IInterfaceHost) part;
}
}
return null;
}
private boolean isDifferentGrid(IInterfaceHost target) {
if (this.selfInterface != null && target != null) {
DualityInterface other = target.getInterfaceDuality();
DualityInterface self = this.selfInterface.getInterfaceDuality();
try {
AENetworkProxy proxy1 = Ae2Reflect.getInterfaceProxy(other);
AENetworkProxy proxy2 = Ae2Reflect.getInterfaceProxy(self);
if (proxy1.getGrid() == proxy2.getGrid()) {
return false;
}
} catch (GridAccessException e) {
return true;
}
}
return invItems != null && invItems.containsItems();
}
public boolean hasSlots() {
return (invFluids != null && invFluids.getTankInfo(side).length > 0) || (invItems != null);
}
@Override
public Iterator<ItemSlot> iterator() {
return new SlotIterator(
invFluids != null ? invFluids.getTankInfo(side) : new FluidTankInfo[0],
invItems != null ? invItems.iterator() : Collections.emptyIterator());
return true;
}
private static class SlotIterator implements Iterator<ItemSlot> {
@@ -16,7 +16,9 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.container.implementations.ContainerUpgradeable;
import appeng.container.implementations.CraftingCPURecord;
import appeng.crafting.MECraftingInventory;
import appeng.helpers.DualityInterface;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.me.helpers.AENetworkProxy;
import appeng.me.storage.MEInventoryHandler;
import appeng.me.storage.MEPassThrough;
import appeng.parts.p2p.PartP2PLiquids;
@@ -35,6 +37,7 @@ public class Ae2Reflect {
private static final Field fCPU_inventory;
private static final Field fCPU_machineSrc;
private static final Field fContainerUpgradeable_upgradeable;
private static final Field fDualInterface_gridProxy;
private static final Method mItemSlot_setExtractable;
private static final Method mCPU_getGrid;
private static final Method mCPU_postChange;
@@ -54,6 +57,7 @@ public class Ae2Reflect {
fCPU_machineSrc = Ae2Reflect.reflectField(CraftingCPUCluster.class, "machineSrc");
fContainerUpgradeable_upgradeable = Ae2Reflect.reflectField(ContainerUpgradeable.class, "upgradeable");
mItemSlot_setExtractable = reflectMethod(ItemSlot.class, "setExtractable", boolean.class);
fDualInterface_gridProxy = reflectField(DualityInterface.class, "gridProxy");
mCPU_getGrid = reflectMethod(CraftingCPUCluster.class, "getGrid");
mCPU_postChange = reflectMethod(
CraftingCPUCluster.class,
@@ -164,6 +168,10 @@ public class Ae2Reflect {
return Ae2Reflect.readField(owner, fContainerUpgradeable_upgradeable);
}
public static AENetworkProxy getInterfaceProxy(DualityInterface owner) {
return Ae2Reflect.readField(owner, fDualInterface_gridProxy);
}
public static void postCPUChange(CraftingCPUCluster cpu, IAEItemStack stack, MachineSource src) {
try {
mCPU_postChange.invoke(cpu, stack, src);