diff --git a/dependencies.gradle b/dependencies.gradle index 2fee83e0..a330e15c 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,15 +2,15 @@ dependencies { compile('com.github.GTNewHorizons:NotEnoughItems:2.3.21-GTNH:dev') - compile('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-156-GTNH:dev') + compile('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-158-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 } compileOnly("com.github.GTNewHorizons:WirelessCraftingTerminal:1.8.9.2:dev") compileOnly('com.github.GTNewHorizons:ForestryMC:4.5.6:dev') - compileOnly('com.github.GTNewHorizons:EnderIO:2.3.1.49:dev') - compileOnly('com.github.GTNewHorizons:EnderCore:0.2.11:dev') + compile('com.github.GTNewHorizons:EnderIO:2.3.1.49:dev') + compile('com.github.GTNewHorizons:EnderCore:0.2.11:dev') compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.41.216:dev') compileOnly('com.github.GTNewHorizons:StructureLib:1.2.0-beta.2:dev') compileOnly('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') diff --git a/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java b/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java index 414130ea..9a8576a1 100644 --- a/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java +++ b/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java @@ -16,9 +16,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; @@ -36,21 +41,24 @@ import com.glodblock.github.util.Util; 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; public static InventoryAdaptor wrap(TileEntity capProvider, ForgeDirection face) { @@ -69,31 +77,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 +155,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 @@ -165,16 +232,24 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor { @Override public boolean containsItems() { if (!this.onmi) { - return checkItemFluids(this.invFluids, this.invItems, this.side); + // If there is no fluid tank or item inventory, it shouldn't send stuff here. + return checkItemFluids(this.invFluids, this.invItems, this.side) > 0; } - boolean result; - for (ForgeDirection dir : ForgeDirection.values()) { - result = checkItemFluids(this.getSideFluid(dir), this.getSideItem(dir), dir); - if (result) { - return true; + boolean anyValid = false; + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + // Avoid sending stuff into itself me network + if (checkValidSide(this.posInterface.getOffSet(dir).getTileEntity(), dir)) { + final int result = checkItemFluids(this.getSideFluid(dir), this.getSideItem(dir), dir.getOpposite()); + if (result == 1) { + return true; + } + if (result != 2) { + anyValid = true; + } } } - return false; + // Same here. if there is no fluid tank or item inventory existed, it shouldn't send stuff here. + return !anyValid; } public boolean hasSlots() { @@ -196,15 +271,47 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor { return null; } - private InventoryAdaptor getSideItem(ForgeDirection direction) { - TileEntity te = this.posInterface.getOffSet(direction).getTileEntity(); - return InventoryAdaptor.getAdaptor(te, direction); + private int fillSideFluid(FluidStack fluid, IFluidHandler tank, ForgeDirection direction, boolean doFill) { + if (tank != null) { + return tank.fill(direction, fluid, doFill); + } + return 0; } - private boolean checkItemFluids(IFluidHandler tank, InventoryAdaptor inv, ForgeDirection direction) { + // 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 boolean isConduit(TileEntity te) { + return ModAndClassUtil.COFH && 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) { - // If this entity doesn't have fluid or item inventory, we just view it as full of things. - return true; + return 2; } if (tank != null && tank.getTankInfo(direction) != null) { List tankInfos = new LinkedList<>(); @@ -237,14 +344,48 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor { hasTank = true; FluidStack fluid = tankInfo.fluid; if (fluid != null && fluid.amount > 0) { - return true; + return 1; } } } - // If this entity doesn't have fluid or item inventory, we just view it as full of things. - return !hasTank && inv == null; + if (!hasTank && inv == null) { + return 2; + } } - return inv != null && inv.containsItems(); + return inv != null && inv.containsItems() ? 1 : 0; + } + + private boolean checkValidSide(TileEntity te, ForgeDirection direction) { + return isDifferentGrid(getInterfaceTE(te, direction.getOpposite())); + } + + 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 true; } private static class SlotIterator implements Iterator { diff --git a/src/main/java/com/glodblock/github/util/Ae2Reflect.java b/src/main/java/com/glodblock/github/util/Ae2Reflect.java index 0b6412a1..645d3e37 100644 --- a/src/main/java/com/glodblock/github/util/Ae2Reflect.java +++ b/src/main/java/com/glodblock/github/util/Ae2Reflect.java @@ -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);