diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index f52f60b..05ff8ed 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -32,6 +32,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.inventory.CraftInventory; import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.util.CraftDamageSource; @@ -111,6 +112,7 @@ import org.ultramine.mods.bukkit.interfaces.entity.IMixinEntityLiving; import org.ultramine.mods.bukkit.interfaces.entity.IMixinEntityLivingBase; import org.ultramine.mods.bukkit.interfaces.entity.player.IMixinPlayerMP; +import org.ultramine.mods.bukkit.interfaces.inventory.IInventoryTransactionProvider; import org.ultramine.mods.bukkit.interfaces.inventory.IMixinContainer; import org.ultramine.mods.bukkit.interfaces.world.IMixinWorld; import org.ultramine.mods.bukkit.util.ArmorPropertiesUM; @@ -1085,6 +1087,8 @@ // Cauldron end player.playerNetServerHandler.processCloseWindow(new net.minecraft.network.play.client.C0DPacketCloseWindow(player.openContainer.windowId)); } + if (player.openContainer == container) + player.openContainer = player.inventoryContainer; CraftServer server = ((IMixinWorld) player.worldObj).getServer(); CraftPlayer craftPlayer = (CraftPlayer) ((IMixinEntity) player).getBukkitEntity(); @@ -1239,7 +1243,19 @@ { InventoryView view = ((IMixinContainer) human.openContainer).getBukkitView(); if(view != null) + { + if (human.openContainer == human.inventoryContainer) + { + IInventoryTransactionProvider topInventoryProvider = (IInventoryTransactionProvider) ((CraftInventory) view.getTopInventory()).getInventory(); + IInventoryTransactionProvider bottomInventoryProvider = (IInventoryTransactionProvider) ((CraftInventory) view.getBottomInventory()).getInventory(); + if (topInventoryProvider.getViewers().isEmpty()) + { + topInventoryProvider.onOpen((CraftHumanEntity) ((IMixinEntity) human).getBukkitEntity()); + bottomInventoryProvider.onOpen((CraftHumanEntity) ((IMixinEntity) human).getBukkitEntity()); + } + } ((IMixinWorld) human.worldObj).getServer().getPluginManager().callEvent(new InventoryCloseEvent(view)); // Cauldron - allow vanilla mods to bypass + } ((IMixinContainer) human.openContainer).transferTo(human.inventoryContainer, (CraftHumanEntity) ((IMixinEntity) human).getBukkitEntity()); ((IMixinContainer) human.openContainer).setOpened(false); } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java index 5180554..975f331 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -7,8 +7,10 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; +import org.ultramine.mods.bukkit.interfaces.inventory.IInventoryTransactionProvider; import org.ultramine.mods.bukkit.util.BukkitUtil; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.ListIterator; @@ -499,15 +501,10 @@ public List getViewers() { - // Cauldron start -// try { -// return this.inventory.getViewers(); -// } catch (AbstractMethodError e) { -// return new java.util.ArrayList(); -// } - // Cauldron end - - return new java.util.ArrayList(); // TODO + if (this.inventory instanceof IInventoryTransactionProvider) + return ((IInventoryTransactionProvider) this.inventory).getViewers(); + else + return Collections.emptyList(); } public String getTitle() diff --git a/src/main/java/org/ultramine/mods/bukkit/asm/ASMTransformer.java b/src/main/java/org/ultramine/mods/bukkit/asm/ASMTransformer.java index ad18377..ceb05e8 100644 --- a/src/main/java/org/ultramine/mods/bukkit/asm/ASMTransformer.java +++ b/src/main/java/org/ultramine/mods/bukkit/asm/ASMTransformer.java @@ -1,6 +1,10 @@ package org.ultramine.mods.bukkit.asm; import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; +import org.ultramine.mods.bukkit.asm.transformers.InventoryClassTransformer; import org.ultramine.mods.bukkit.asm.transformers.LightningBoltConstructorTransformer; public class ASMTransformer implements IClassTransformer @@ -8,8 +12,34 @@ @Override public byte[] transform(String name, String transformedName, byte[] basicClass) { - if(transformedName.equals("net.minecraft.entity.effect.EntityLightningBolt")) + if (basicClass == null) + return null; + if (transformedName.equals("net.minecraft.entity.effect.EntityLightningBolt")) return LightningBoltConstructorTransformer.transformConstructor(basicClass); + if (doesClassImplementIInventory(basicClass)) + return InventoryClassTransformer.transformClass(basicClass); return basicClass; } + + private boolean doesClassImplementIInventory(byte[] someClass) + { + final boolean[] doesClassImplementIInventory = {false}; + ClassReader classReader = new ClassReader(someClass); + final ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5) + { + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) + { + for (String interfaceName : interfaces) + if ((interfaceName.equals("rb") || interfaceName.equals("rl") || interfaceName.equals("net/minecraft/inventory/ISidedInventory") || interfaceName.equals("aph")) && (access & Opcodes.ACC_INTERFACE) == 0) + { + doesClassImplementIInventory[0] = true; + break; + } + super.visit(version, access, name, signature, superName, interfaces); + } + }; + classReader.accept(classVisitor, 0); + return doesClassImplementIInventory[0]; + } } diff --git a/src/main/java/org/ultramine/mods/bukkit/asm/transformers/InventoryClassTransformer.java b/src/main/java/org/ultramine/mods/bukkit/asm/transformers/InventoryClassTransformer.java new file mode 100644 index 0000000..b111610 --- /dev/null +++ b/src/main/java/org/ultramine/mods/bukkit/asm/transformers/InventoryClassTransformer.java @@ -0,0 +1,115 @@ +package org.ultramine.mods.bukkit.asm.transformers; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; + +import static org.objectweb.asm.Opcodes.*; + +public class InventoryClassTransformer +{ + public static byte[] transformClass(byte[] basicClass) + { + ClassNode cNode = new ClassNode(); + new ClassReader(basicClass).accept(cNode, 0); + ClassWriter cWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + // implements IInventoryTransactionProvider + cNode.interfaces.add("org/ultramine/mods/bukkit/interfaces/inventory/IInventoryTransactionProvider"); + + // private List transaction; + cWriter.visitField(ACC_PRIVATE, "transaction", "Ljava/util/List;", "Ljava/util/List;", null).visitEnd(); + +// public void onOpen(CraftHumanEntity craftHumanEntity) +// { +// if (this.transaction == null) +// { +// this.transaction = new ArrayList(1); +// } +// this.transaction.add((HumanEntity)craftHumanEntity); +// } + MethodVisitor mv = cWriter.visitMethod(ACC_PUBLIC, "onOpen", "(Lorg/bukkit/craftbukkit/v1_7_R4/entity/CraftHumanEntity;)V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(NEW, "java/util/ArrayList"); + mv.visitInsn(DUP); + mv.visitInsn(ICONST_1); + mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "", "(I)V", false); + mv.visitFieldInsn(PUTFIELD, cNode.name, "transaction", "Ljava/util/List;"); + mv.visitLabel(l1); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true); + mv.visitInsn(POP); + mv.visitInsn(RETURN); + +// public void onClose(CraftHumanEntity craftHumanEntity) +// { +// if (this.transaction != null) +// { +// this.transaction.remove(craftHumanEntity); +// if (this.transaction.isEmpty()) +// { +// this.transaction = null; +// } +// } +// } + mv = cWriter.visitMethod(ACC_PUBLIC, "onClose", "(Lorg/bukkit/craftbukkit/v1_7_R4/entity/CraftHumanEntity;)V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + Label t1 = new Label(); + mv.visitJumpInsn(IFNULL, t1); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "remove", "(Ljava/lang/Object;)Z", true); + mv.visitInsn(POP); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "isEmpty", "()Z", true); + mv.visitJumpInsn(IFEQ, t1); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(ACONST_NULL); + mv.visitFieldInsn(PUTFIELD, cNode.name, "transaction", "Ljava/util/List;"); + mv.visitLabel(t1); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitInsn(RETURN); + mv.visitEnd(); + +// public List getViewers() +// { +// if (this.transaction == null) +// { +// return Collections.emptyList(); +// } +// return this.transaction; +// } + mv = cWriter.visitMethod(ACC_PUBLIC, "getViewers", "()Ljava/util/List;", "()Ljava/util/List;", null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + Label k1 = new Label(); + mv.visitJumpInsn(IFNONNULL, k1); + mv.visitMethodInsn(INVOKESTATIC, "java/util/Collections", "emptyList", "()Ljava/util/List;", false); + mv.visitInsn(ARETURN); + mv.visitLabel(k1); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, cNode.name, "transaction", "Ljava/util/List;"); + mv.visitInsn(ARETURN); + + mv.visitEnd(); + cNode.accept(cWriter); + return cWriter.toByteArray(); + } +} diff --git a/src/main/java/org/ultramine/mods/bukkit/interfaces/inventory/IInventoryTransactionProvider.java b/src/main/java/org/ultramine/mods/bukkit/interfaces/inventory/IInventoryTransactionProvider.java new file mode 100644 index 0000000..66bd651 --- /dev/null +++ b/src/main/java/org/ultramine/mods/bukkit/interfaces/inventory/IInventoryTransactionProvider.java @@ -0,0 +1,15 @@ +package org.ultramine.mods.bukkit.interfaces.inventory; + +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.entity.HumanEntity; + +import java.util.List; + +public interface IInventoryTransactionProvider +{ + void onOpen(CraftHumanEntity who); + + void onClose(CraftHumanEntity who); + + List getViewers(); +} diff --git a/src/main/java/org/ultramine/mods/bukkit/mixin/inventory/MixinContainer.java b/src/main/java/org/ultramine/mods/bukkit/mixin/inventory/MixinContainer.java index 8380caa..9b070fa 100644 --- a/src/main/java/org/ultramine/mods/bukkit/mixin/inventory/MixinContainer.java +++ b/src/main/java/org/ultramine/mods/bukkit/mixin/inventory/MixinContainer.java @@ -33,6 +33,7 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.ultramine.mods.bukkit.interfaces.entity.player.IMixinPlayer; +import org.ultramine.mods.bukkit.interfaces.inventory.IInventoryTransactionProvider; import org.ultramine.mods.bukkit.interfaces.inventory.IMixinContainer; import org.ultramine.mods.bukkit.interfaces.world.IMixinWorld; @@ -175,7 +176,89 @@ @Override public void transferTo(Container other, CraftHumanEntity player) { - + InventoryView source = player.getOpenInventory(), destination = ((IMixinContainer) other).getBukkitView(); + if (source != null) + { + if (source.getTopInventory() instanceof CraftInventory) + { + IInventory topInventory = ((CraftInventory) source.getTopInventory()).getInventory(); + if (topInventory instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider topInventoryProvider = (IInventoryTransactionProvider) topInventory; + if (topInventoryProvider.getViewers().contains(player)) + topInventoryProvider.onClose(player); + } + } + else + { + if (source.getTopInventory() instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider topInventoryProvider = (IInventoryTransactionProvider) source.getTopInventory(); + if (topInventoryProvider.getViewers().contains(player)) + topInventoryProvider.onClose(player); + } + } + if (source.getBottomInventory() instanceof CraftInventory) + { + IInventory bottomInventory = ((CraftInventory) source.getBottomInventory()).getInventory(); + if (bottomInventory instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider bottomInventoryProvider = (IInventoryTransactionProvider) bottomInventory; + if (bottomInventoryProvider.getViewers().contains(player)) + bottomInventoryProvider.onClose(player); + } + } + else + { + if (source.getBottomInventory() instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider bottomInventoryProvider = (IInventoryTransactionProvider) source.getBottomInventory(); + if (bottomInventoryProvider.getViewers().contains(player)) + bottomInventoryProvider.onClose(player); + } + } + } + if (destination != null) + { + if (destination.getTopInventory() instanceof CraftInventory) + { + IInventory topInventory = ((CraftInventory) destination.getTopInventory()).getInventory(); + if (topInventory instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider topInventoryProvider = (IInventoryTransactionProvider) topInventory; + if (!topInventoryProvider.getViewers().contains(player)) + topInventoryProvider.onOpen(player); + } + } + else + { + if (destination.getTopInventory() instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider topInventoryProvider = (IInventoryTransactionProvider) destination.getTopInventory(); + if (!topInventoryProvider.getViewers().contains(player)) + topInventoryProvider.onOpen(player); + } + } + if (destination.getBottomInventory() instanceof CraftInventory) + { + IInventory bottomInventory = ((CraftInventory) destination.getBottomInventory()).getInventory(); + if (bottomInventory instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider bottomInventoryProvider = (IInventoryTransactionProvider) bottomInventory; + if (!bottomInventoryProvider.getViewers().contains(player)) + bottomInventoryProvider.onOpen(player); + } + } + else + { + if (destination.getBottomInventory() instanceof IInventoryTransactionProvider) + { + IInventoryTransactionProvider bottomInventoryProvider = (IInventoryTransactionProvider) destination.getBottomInventory(); + if (!bottomInventoryProvider.getViewers().contains(player)) + bottomInventoryProvider.onOpen(player); + } + } + } } @Final diff --git a/src/main/java/org/ultramine/mods/bukkit/mixin/management/MixinItemInWorldManager.java b/src/main/java/org/ultramine/mods/bukkit/mixin/management/MixinItemInWorldManager.java index 5087442..74de99c 100644 --- a/src/main/java/org/ultramine/mods/bukkit/mixin/management/MixinItemInWorldManager.java +++ b/src/main/java/org/ultramine/mods/bukkit/mixin/management/MixinItemInWorldManager.java @@ -4,6 +4,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; +import net.minecraft.inventory.ContainerPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -242,7 +243,7 @@ else if(!p_73078_1_.isSneaking() || p_73078_3_ == null || p_73078_1_.getHeldItem().getItem().doesSneakBypassUse(p_73078_2_, p_73078_4_, p_73078_5_, p_73078_6_, p_73078_1_)) { denyResult |= block.onBlockActivated(p_73078_2_, p_73078_4_, p_73078_5_, p_73078_6_, p_73078_1_, p_73078_7_, p_73078_8_, p_73078_9_, p_73078_10_); - if (thisPlayerMP != null) + if (thisPlayerMP != null && !(thisPlayerMP.openContainer instanceof ContainerPlayer)) { if (((IMixinContainer) thisPlayerMP.openContainer).getBukkitView() == null) {