From e8825d74e76bea78611680711d9a969dc8c7753e Mon Sep 17 00:00:00 2001 From: GlodBlock <1356392126@qq.com> Date: Mon, 1 Aug 2022 14:52:57 +0800 Subject: [PATCH] fix drops leak to item cell when discretizer go offline --- dependencies.gradle | 1 - .../common/tile/TileFluidDiscretizer.java | 19 ------- .../github/coremod/hooker/CoreModHooks.java | 54 +++++++++++++++++++ .../transform/CraftingCpuTransformer.java | 25 +++++++++ .../com/glodblock/github/util/Ae2Reflect.java | 52 ++++++++++++++++++ 5 files changed, 131 insertions(+), 20 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 8dc68525b..344f1b3a0 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -21,6 +21,5 @@ dependencies { compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.3.19-GTNH:dev') {transitive = false} compileOnly("com.github.GTNewHorizons:EnderIO:2.3.1.29:dev") {transitive = false} - runtime("com.github.GTNewHorizons:Baubles:1.0.1.14:dev") } diff --git a/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java b/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java index 813ff32e2..44332f2ff 100644 --- a/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java +++ b/src/main/java/com/glodblock/github/common/tile/TileFluidDiscretizer.java @@ -129,25 +129,6 @@ public void onStorageUpdate(MENetworkStorageEvent event) { updateState(); } - @MENetworkEventSubscribe - public void onBootUp(MENetworkBootingStatusChange event) { - try { - IMEInventory inventory = this.getProxy().getStorage().getItemInventory(); - IItemList items = inventory.getAvailableItems(AEApi.instance().storage().createItemList()); - IItemList drops = AEApi.instance().storage().createItemList(); - for (IAEItemStack item : items) { - if (item != null && item.getItem() instanceof ItemFluidDrop) { - drops.add(item); - } - } - for (IAEItemStack drop : drops) { - inventory.extractItems(drop, Actionable.MODULATE, ownActionSource); - inventory.injectItems(drop, Actionable.MODULATE, ownActionSource); - } - } catch (GridAccessException ignored) { - } - } - private class FluidDiscretizingInventory implements IMEInventory, IMEMonitorHandlerReceiver { private final MEInventoryHandler invHandler = new MEInventoryHandler<>(this, getChannel()); diff --git a/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java b/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java index 1ec8742a4..9dff4263e 100644 --- a/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java +++ b/src/main/java/com/glodblock/github/coremod/hooker/CoreModHooks.java @@ -1,11 +1,17 @@ package com.glodblock.github.coremod.hooker; +import appeng.api.config.Actionable; import appeng.api.networking.IGrid; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.IMachineSet; +import appeng.api.networking.storage.IStorageGrid; +import appeng.api.storage.IMEInventory; +import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; +import appeng.crafting.MECraftingInventory; import appeng.me.MachineSet; +import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.parts.misc.PartInterface; import appeng.tile.misc.TileInterface; import appeng.util.InventoryAdaptor; @@ -16,6 +22,7 @@ import com.glodblock.github.inventory.FluidConvertingInventoryAdaptor; import com.glodblock.github.inventory.FluidConvertingInventoryCrafting; import com.glodblock.github.loader.ItemAndBlockHolder; +import com.glodblock.github.util.Ae2Reflect; import com.glodblock.github.util.SetBackedMachineSet; import com.glodblock.github.util.Util; import com.google.common.collect.Sets; @@ -104,4 +111,51 @@ public static long getFluidSize(IAEItemStack aeStack) { else return aeStack.getStackSize(); } + public static void storeFluidItem(CraftingCPUCluster instance) { + final IGrid g = Ae2Reflect.getGrid(instance); + + if( g == null ) + { + return; + } + + final IStorageGrid sg = g.getCache( IStorageGrid.class ); + final IMEInventory ii = sg.getItemInventory(); + final IMEInventory jj = sg.getFluidInventory(); + final MECraftingInventory inventory = Ae2Reflect.getCPUInventory(instance); + + for( IAEItemStack is : inventory.getItemList() ) + { + is = inventory.extractItems( is.copy(), Actionable.MODULATE, Ae2Reflect.getCPUSource(instance) ); + + if( is != null ) + { + Ae2Reflect.postCPUChange(instance, is, Ae2Reflect.getCPUSource(instance)); + if (is.getItem() instanceof ItemFluidDrop) { + IAEFluidStack fluidDrop = ItemFluidDrop.getAeFluidStack(is); + fluidDrop = jj.injectItems(fluidDrop, Actionable.MODULATE, Ae2Reflect.getCPUSource(instance)); + if (fluidDrop == null) { + is = null; + } else { + is.setStackSize(fluidDrop.getStackSize()); + } + } else { + is = ii.injectItems(is, Actionable.MODULATE, Ae2Reflect.getCPUSource(instance)); + } + } + + if( is != null ) + { + inventory.injectItems( is, Actionable.MODULATE, Ae2Reflect.getCPUSource(instance) ); + } + } + + if( inventory.getItemList().isEmpty() ) + { + Ae2Reflect.setCPUInventory(instance, new MECraftingInventory()); + } + + Ae2Reflect.markCPUDirty(instance); + } + } diff --git a/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java b/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java index 985ec9c33..2c3c8a74d 100644 --- a/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java +++ b/src/main/java/com/glodblock/github/coremod/transform/CraftingCpuTransformer.java @@ -29,6 +29,8 @@ private static class TransformCraftingCPUCluster extends ClassVisitor { public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if (name.equals("executeCrafting")) { return new TransformExecuteCrafting(api, super.visitMethod(access, name, desc, signature, exceptions)); + } else if (name.equals("cancel")) { + return new TransformStoreItems(api, super.visitMethod(access, name, desc, signature, exceptions)); } return super.visitMethod(access, name, desc, signature, exceptions); } @@ -104,4 +106,27 @@ public void visitMethodInsn(int opcode, String owner, String name, String desc, } + private static class TransformStoreItems extends MethodVisitor { + + TransformStoreItems(int api, MethodVisitor mv) { + super(api, mv); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { + if (opcode == Opcodes.INVOKESPECIAL + && owner.equals("appeng/me/cluster/implementations/CraftingCPUCluster") && name.equals("storeItems")) { + super.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/glodblock/github/coremod/hooker/CoreModHooks", + "storeFluidItem", + "(Lappeng/me/cluster/implementations/CraftingCPUCluster;)V", + false + ); + } else { + super.visitMethodInsn(opcode, owner, name, desc, itf); + } + } + + } + } diff --git a/src/main/java/com/glodblock/github/util/Ae2Reflect.java b/src/main/java/com/glodblock/github/util/Ae2Reflect.java index 82dcdb37e..1ca3c2d56 100644 --- a/src/main/java/com/glodblock/github/util/Ae2Reflect.java +++ b/src/main/java/com/glodblock/github/util/Ae2Reflect.java @@ -1,10 +1,16 @@ package com.glodblock.github.util; import appeng.api.implementations.IUpgradeableHost; +import appeng.api.networking.IGrid; import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.security.MachineSource; import appeng.api.storage.IMEInventory; +import appeng.api.storage.data.IAEItemStack; import appeng.container.implementations.ContainerUpgradeable; import appeng.container.implementations.CraftingCPURecord; +import appeng.crafting.MECraftingInventory; +import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.me.storage.MEInventoryHandler; import appeng.me.storage.MEPassThrough; import appeng.util.inv.ItemSlot; @@ -23,7 +29,12 @@ public class Ae2Reflect { private static final Field fCPU_myName; private static final Field fCPU_processors; private static final Field fCPU_size; + private static final Field fCPU_inventory; + private static final Field fCPU_machineSrc; private static final Method mItemSlot_setExtractable; + private static final Method mCPU_getGrid; + private static final Method mCPU_postChange; + private static final Method mCPU_markDirty; static { try { @@ -34,7 +45,12 @@ public class Ae2Reflect { fCPU_myName = Ae2Reflect.reflectField(CraftingCPURecord.class, "myName"); fCPU_processors = Ae2Reflect.reflectField(CraftingCPURecord.class, "processors"); fCPU_size = Ae2Reflect.reflectField(CraftingCPURecord.class, "size"); + fCPU_inventory = Ae2Reflect.reflectField(CraftingCPUCluster.class, "inventory"); + fCPU_machineSrc = Ae2Reflect.reflectField(CraftingCPUCluster.class, "machineSrc"); mItemSlot_setExtractable = reflectMethod(ItemSlot.class, "setExtractable", boolean.class); + mCPU_getGrid = reflectMethod(CraftingCPUCluster.class, "getGrid"); + mCPU_postChange = reflectMethod(CraftingCPUCluster.class, "postChange", IAEItemStack.class, BaseActionSource.class); + mCPU_markDirty = reflectMethod(CraftingCPUCluster.class, "markDirty"); } catch (Exception e) { throw new IllegalStateException("Failed to initialize AE2 reflection hacks!", e); } @@ -114,4 +130,40 @@ public static IUpgradeableHost getUpgradeList(ContainerUpgradeable container) { return Ae2Reflect.readField(container, fInventory_containerUpgrade); } + public static IGrid getGrid(CraftingCPUCluster cpu) { + try { + return (IGrid) mCPU_getGrid.invoke(cpu); + } catch (Exception e) { + throw new IllegalStateException("Failed to invoke method: " + mCPU_getGrid, e); + } + } + + public static MECraftingInventory getCPUInventory(CraftingCPUCluster cpu) { + return Ae2Reflect.readField(cpu, fCPU_inventory); + } + + public static void setCPUInventory(CraftingCPUCluster cpu, MECraftingInventory value) { + Ae2Reflect.writeField(cpu, fCPU_inventory, value); + } + + public static MachineSource getCPUSource(CraftingCPUCluster cpu) { + return Ae2Reflect.readField(cpu, fCPU_machineSrc); + } + + public static void postCPUChange(CraftingCPUCluster cpu, IAEItemStack stack, MachineSource src) { + try { + mCPU_postChange.invoke(cpu, stack, src); + } catch (Exception e) { + throw new IllegalStateException("Failed to invoke method: " + mCPU_postChange, e); + } + } + + public static void markCPUDirty(CraftingCPUCluster cpu) { + try { + mCPU_markDirty.invoke(cpu); + } catch (Exception e) { + throw new IllegalStateException("Failed to invoke method: " + mCPU_markDirty, e); + } + } + }