diff --git a/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java b/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java index 916427b..8f6d86c 100644 --- a/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java +++ b/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/AnySilentContainer.java @@ -1,51 +1,63 @@ /* * Copyright (C) 2011-2014 lishid. All rights reserved. - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_10_R1; +import java.lang.reflect.Field; + import com.lishid.openinv.internal.IAnySilentContainer; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryView; import net.minecraft.server.v1_10_R1.AxisAlignedBB; import net.minecraft.server.v1_10_R1.Block; import net.minecraft.server.v1_10_R1.BlockChest; import net.minecraft.server.v1_10_R1.BlockEnderChest; import net.minecraft.server.v1_10_R1.BlockPosition; -import net.minecraft.server.v1_10_R1.Container; import net.minecraft.server.v1_10_R1.Entity; import net.minecraft.server.v1_10_R1.EntityOcelot; import net.minecraft.server.v1_10_R1.EntityPlayer; import net.minecraft.server.v1_10_R1.EnumDirection; +import net.minecraft.server.v1_10_R1.EnumGamemode; import net.minecraft.server.v1_10_R1.ITileInventory; import net.minecraft.server.v1_10_R1.InventoryEnderChest; import net.minecraft.server.v1_10_R1.InventoryLargeChest; -import net.minecraft.server.v1_10_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_10_R1.PlayerInteractManager; import net.minecraft.server.v1_10_R1.StatisticList; import net.minecraft.server.v1_10_R1.TileEntity; import net.minecraft.server.v1_10_R1.TileEntityChest; import net.minecraft.server.v1_10_R1.TileEntityEnderChest; import net.minecraft.server.v1_10_R1.World; -import org.bukkit.craftbukkit.v1_10_R1.event.CraftEventFactory; - public class AnySilentContainer implements IAnySilentContainer { + private Field playerInteractManagerGamemode; + + public AnySilentContainer() { + try { + this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); + this.playerInteractManagerGamemode.setAccessible(true); + } catch (Exception e) { + System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); + e.printStackTrace(); + } + } + @Override public boolean isAnySilentContainer(org.bukkit.block.Block block) { return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; @@ -144,7 +156,6 @@ public class AnySilentContainer implements IAnySilentContainer { ITileInventory tileInventory = (ITileInventory) tile; Block block = world.getType(blockPosition).getBlock(); - Container container = null; if (block instanceof BlockChest) { for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { @@ -176,42 +187,64 @@ public class AnySilentContainer implements IAnySilentContainer { } else if (blockChest.g == BlockChest.Type.TRAP) { player.b(StatisticList.W); } - - if (silentchest) { - container = new SilentContainerChest(player.inventory, tileInventory, player); - } } - // AnyChest only - SilentChest not active or container unsupported - if (!silentchest || container == null) { + // AnyChest only - SilentChest not active, container unsupported, or unnecessary. + if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { player.openContainer(tileInventory); return true; } - // SilentChest - try { - // Call InventoryOpenEvent - container = CraftEventFactory.callInventoryOpenEvent(player, container, false); - if (container == null) { - return false; - } - - // Open window - int windowId = player.nextContainerCounter(); - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, tileInventory.getContainerName(), tileInventory.getScoreboardDisplayName(), tileInventory.getSize())); - player.activeContainer = container; - player.activeContainer.windowId = windowId; - player.activeContainer.addSlotListener(player); - - return true; - } catch (Exception e) { - e.printStackTrace(); - p.sendMessage(ChatColor.RED + "Error while sending silent container."); + // SilentChest requires access to setting players' gamemode directly. + if (this.playerInteractManagerGamemode == null) { return false; } + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.openContainer(tileInventory); + this.forceGameMode(player, gamemode); + return true; } @Override - public void deactivateContainer(final Player bukkitPlayer) {} + public void deactivateContainer(final Player bukkitPlayer) { + if (this.playerInteractManagerGamemode == null) { + return; + } + + InventoryView view = bukkitPlayer.getOpenInventory(); + switch (view.getType()) { + case CHEST: + case ENDER_CHEST: + break; + default: + return; + } + + EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.activeContainer.b(player); + player.activeContainer = player.defaultContainer; + this.forceGameMode(player, gamemode); + } + + private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { + if (this.playerInteractManagerGamemode == null) { + // No need to warn repeatedly, error on startup and lack of function should be enough. + return; + } + try { + if (!this.playerInteractManagerGamemode.isAccessible()) { + // Just in case, ensure accessible. + this.playerInteractManagerGamemode.setAccessible(true); + } + this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java b/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java deleted file mode 100644 index 8705bc3..0000000 --- a/internal/v1_10_R1/src/main/java/com/lishid/openinv/internal/v1_10_R1/SilentContainerChest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2014 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_10_R1; - -import net.minecraft.server.v1_10_R1.ContainerChest; -import net.minecraft.server.v1_10_R1.EntityHuman; -import net.minecraft.server.v1_10_R1.IInventory; -import net.minecraft.server.v1_10_R1.ItemStack; -import net.minecraft.server.v1_10_R1.PlayerInventory; - -public class SilentContainerChest extends ContainerChest { - - public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { - super(i1, i2, e1); - // Send close signal - i2.closeContainer(e1); - } - - @Override - public void b(EntityHuman entityHuman) { - // Don't send close signal twice, might screw up - PlayerInventory playerinventory = entityHuman.inventory; - - if (playerinventory.getCarried() != null) { - ItemStack carried = playerinventory.getCarried(); - playerinventory.setCarried(null); - entityHuman.drop(carried, false); - } - } - -} diff --git a/internal/v1_12_R1/src/main/java/com/lishid/openinv/internal/v1_12_R1/AnySilentContainer.java b/internal/v1_12_R1/src/main/java/com/lishid/openinv/internal/v1_12_R1/AnySilentContainer.java index dfde6be..6502758 100644 --- a/internal/v1_12_R1/src/main/java/com/lishid/openinv/internal/v1_12_R1/AnySilentContainer.java +++ b/internal/v1_12_R1/src/main/java/com/lishid/openinv/internal/v1_12_R1/AnySilentContainer.java @@ -1,11 +1,17 @@ /* - * Copyright (C) 2011-2014 lishid. All rights reserved. This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, version 3. This program is distributed in the hope that it will - * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should - * have received a copy of the GNU General Public License along with this program. If not, see - * . + * Copyright (C) 2011-2014 lishid. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_12_R1; @@ -56,6 +62,101 @@ public class AnySilentContainer implements IAnySilentContainer { } } + @Override + public boolean isAnySilentContainer(final org.bukkit.block.Block block) { + if (block.getType() == Material.ENDER_CHEST) { + return true; + } + BlockState state = block.getState(); + return state instanceof org.bukkit.block.Chest + || state instanceof org.bukkit.block.ShulkerBox; + } + + @Override + public boolean isAnyContainerNeeded(final Player p, final org.bukkit.block.Block b) { + EntityPlayer player = PlayerDataManager.getHandle(p); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + IBlockData blockData = world.getType(blockPosition); + Block block = blockData.getBlock(); + + if (block instanceof BlockShulkerBox) { + return this.isBlockedShulkerBox(world, blockPosition, blockData); + } + + if (block instanceof BlockEnderChest) { + // Ender chests are not blocked by ocelots. + return world.getType(blockPosition.up()).m(); + } + + // Check if chest is blocked or has an ocelot on top + if (this.isBlockedChest(world, blockPosition)) { + return true; + } + + // Check for matching adjacent chests that are blocked or have an ocelot on top + for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { + BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); + Block localBlock = world.getType(localBlockPosition).getBlock(); + + if (localBlock != block) { + continue; + } + + TileEntity localTileEntity = world.getTileEntity(localBlockPosition); + if (!(localTileEntity instanceof TileEntityChest)) { + continue; + } + + if (this.isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedShulkerBox(final World world, final BlockPosition blockPosition, + final IBlockData blockData) { + // For reference, look at net.minecraft.server.BlockShulkerBox + TileEntity tile = world.getTileEntity(blockPosition); + + if (!(tile instanceof TileEntityShulkerBox)) { + return false; + } + + EnumDirection enumDirection = blockData.get(BlockShulkerBox.a); + if (((TileEntityShulkerBox) tile).p() == TileEntityShulkerBox.AnimationPhase.CLOSED) { + AxisAlignedBB axisAlignedBB = Block.j.b(0.5F * enumDirection.getAdjacentX(), + 0.5F * enumDirection.getAdjacentY(), 0.5F * enumDirection.getAdjacentZ()) + .a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(), + enumDirection.getAdjacentZ()); + + return world.a(axisAlignedBB.a(blockPosition.shift(enumDirection))); + } + + return false; + } + + private boolean isBlockedChest(final World world, final BlockPosition blockPosition) { + // For reference, loot at net.minecraft.server.BlockChest + return world.getType(blockPosition.up()).l() || this.hasOcelotOnTop(world, blockPosition); + } + + private boolean hasOcelotOnTop(final World world, final BlockPosition blockPosition) { + for (Entity localEntity : world.a(EntityOcelot.class, + new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, + blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, + blockPosition.getZ() + 1))) { + EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; + if (localEntityOcelot.isSitting()) { + return true; + } + } + + return false; + } + @Override public boolean activateContainer(final Player bukkitPlayer, final boolean silentchest, final org.bukkit.block.Block bukkitBlock) { @@ -189,99 +290,4 @@ public class AnySilentContainer implements IAnySilentContainer { } } - private boolean hasOcelotOnTop(final World world, final BlockPosition blockPosition) { - for (Entity localEntity : world.a(EntityOcelot.class, - new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1, - blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2, - blockPosition.getZ() + 1))) { - EntityOcelot localEntityOcelot = (EntityOcelot) localEntity; - if (localEntityOcelot.isSitting()) { - return true; - } - } - - return false; - } - - @Override - public boolean isAnyContainerNeeded(final Player p, final org.bukkit.block.Block b) { - EntityPlayer player = PlayerDataManager.getHandle(p); - World world = player.world; - BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); - IBlockData blockData = world.getType(blockPosition); - Block block = blockData.getBlock(); - - if (block instanceof BlockShulkerBox) { - return this.isBlockedShulkerBox(world, blockPosition, blockData); - } - - if (block instanceof BlockEnderChest) { - // Ender chests are not blocked by ocelots. - return world.getType(blockPosition.up()).m(); - } - - // Check if chest is blocked or has an ocelot on top - if (this.isBlockedChest(world, blockPosition)) { - return true; - } - - // Check for matching adjacent chests that are blocked or have an ocelot on top - for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { - BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); - Block localBlock = world.getType(localBlockPosition).getBlock(); - - if (localBlock != block) { - continue; - } - - TileEntity localTileEntity = world.getTileEntity(localBlockPosition); - if (!(localTileEntity instanceof TileEntityChest)) { - continue; - } - - if (this.isBlockedChest(world, localBlockPosition)) { - return true; - } - } - - return false; - } - - @Override - public boolean isAnySilentContainer(final org.bukkit.block.Block block) { - if (block.getType() == Material.ENDER_CHEST) { - return true; - } - BlockState state = block.getState(); - return state instanceof org.bukkit.block.Chest - || state instanceof org.bukkit.block.ShulkerBox; - } - - private boolean isBlockedChest(final World world, final BlockPosition blockPosition) { - // For reference, loot at net.minecraft.server.BlockChest - return world.getType(blockPosition.up()).l() || this.hasOcelotOnTop(world, blockPosition); - } - - private boolean isBlockedShulkerBox(final World world, final BlockPosition blockPosition, - final IBlockData blockData) { - // For reference, look at net.minecraft.server.BlockShulkerBox - TileEntity tile = world.getTileEntity(blockPosition); - - if (!(tile instanceof TileEntityShulkerBox)) { - return false; - } - - EnumDirection enumDirection = blockData.get(BlockShulkerBox.a); - if (((TileEntityShulkerBox) tile).p() == TileEntityShulkerBox.AnimationPhase.CLOSED) { - AxisAlignedBB axisAlignedBB = Block.j.b(0.5F * enumDirection.getAdjacentX(), - 0.5F * enumDirection.getAdjacentY(), 0.5F * enumDirection.getAdjacentZ()) - .a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(), - enumDirection.getAdjacentZ()); - - return world.a(axisAlignedBB.a(blockPosition.shift(enumDirection))); - } - - return false; - } - } diff --git a/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java b/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java index b5cb77a..c579867 100644 --- a/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java +++ b/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/AnySilentContainer.java @@ -1,49 +1,61 @@ /* * Copyright (C) 2011-2014 lishid. All rights reserved. - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_8_R1; +import java.lang.reflect.Field; + import com.lishid.openinv.internal.IAnySilentContainer; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryView; import net.minecraft.server.v1_8_R1.AxisAlignedBB; import net.minecraft.server.v1_8_R1.Block; import net.minecraft.server.v1_8_R1.BlockChest; import net.minecraft.server.v1_8_R1.BlockEnderChest; import net.minecraft.server.v1_8_R1.BlockPosition; -import net.minecraft.server.v1_8_R1.Container; import net.minecraft.server.v1_8_R1.EntityOcelot; import net.minecraft.server.v1_8_R1.EntityPlayer; import net.minecraft.server.v1_8_R1.EnumDirection; +import net.minecraft.server.v1_8_R1.EnumGamemode; import net.minecraft.server.v1_8_R1.ITileInventory; import net.minecraft.server.v1_8_R1.InventoryEnderChest; import net.minecraft.server.v1_8_R1.InventoryLargeChest; -import net.minecraft.server.v1_8_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_8_R1.PlayerInteractManager; import net.minecraft.server.v1_8_R1.TileEntity; import net.minecraft.server.v1_8_R1.TileEntityChest; import net.minecraft.server.v1_8_R1.TileEntityEnderChest; import net.minecraft.server.v1_8_R1.World; -import org.bukkit.craftbukkit.v1_8_R1.event.CraftEventFactory; - public class AnySilentContainer implements IAnySilentContainer { + private Field playerInteractManagerGamemode; + + public AnySilentContainer() { + try { + this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); + this.playerInteractManagerGamemode.setAccessible(true); + } catch (Exception e) { + System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); + e.printStackTrace(); + } + } + @Override public boolean isAnySilentContainer(org.bukkit.block.Block block) { return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; @@ -145,7 +157,6 @@ public class AnySilentContainer implements IAnySilentContainer { ITileInventory tileInventory = (ITileInventory) tile; Block block = world.getType(blockPosition).getBlock(); - Container container = null; if (block instanceof BlockChest) { for (EnumDirection localEnumDirection : EnumDirection.values()) { @@ -166,7 +177,7 @@ public class AnySilentContainer implements IAnySilentContainer { continue; } - if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + if (localEnumDirection == EnumDirection.WEST || localEnumDirection == EnumDirection.NORTH) { tileInventory = new InventoryLargeChest("container.chestDouble", (TileEntityChest) localTileEntity, tileInventory); } else { @@ -175,42 +186,64 @@ public class AnySilentContainer implements IAnySilentContainer { } break; } - - if (silentchest) { - container = new SilentContainerChest(player.inventory, tileInventory, player); - } } - // AnyChest only - SilentChest not active or container unsupported - if (!silentchest || container == null) { + // AnyChest only - SilentChest not active, container unsupported, or unnecessary. + if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { player.openContainer(tileInventory); return true; } - // SilentChest - try { - // Call InventoryOpenEvent - container = CraftEventFactory.callInventoryOpenEvent(player, container, false); - if (container == null) { - return false; - } - - // Open window - int windowId = player.nextContainerCounter(); - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, tileInventory.getContainerName(), tileInventory.getScoreboardDisplayName(), tileInventory.getSize())); - player.activeContainer = container; - player.activeContainer.windowId = windowId; - player.activeContainer.addSlotListener(player); - - return true; - } catch (Exception e) { - e.printStackTrace(); - p.sendMessage(ChatColor.RED + "Error while sending silent container."); + // SilentChest requires access to setting players' gamemode directly. + if (this.playerInteractManagerGamemode == null) { return false; } + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.openContainer(tileInventory); + this.forceGameMode(player, gamemode); + return true; } @Override - public void deactivateContainer(final Player bukkitPlayer) {} + public void deactivateContainer(final Player bukkitPlayer) { + if (this.playerInteractManagerGamemode == null) { + return; + } + + InventoryView view = bukkitPlayer.getOpenInventory(); + switch (view.getType()) { + case CHEST: + case ENDER_CHEST: + break; + default: + return; + } + + EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.activeContainer.b(player); + player.activeContainer = player.defaultContainer; + this.forceGameMode(player, gamemode); + } + + private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { + if (this.playerInteractManagerGamemode == null) { + // No need to warn repeatedly, error on startup and lack of function should be enough. + return; + } + try { + if (!this.playerInteractManagerGamemode.isAccessible()) { + // Just in case, ensure accessible. + this.playerInteractManagerGamemode.setAccessible(true); + } + this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java b/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java deleted file mode 100644 index c47baa7..0000000 --- a/internal/v1_8_R1/src/main/java/com/lishid/openinv/internal/v1_8_R1/SilentContainerChest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2014 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_8_R1; - -import net.minecraft.server.v1_8_R1.ContainerChest; -import net.minecraft.server.v1_8_R1.EntityHuman; -import net.minecraft.server.v1_8_R1.IInventory; -import net.minecraft.server.v1_8_R1.ItemStack; -import net.minecraft.server.v1_8_R1.PlayerInventory; - -public class SilentContainerChest extends ContainerChest { - - public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { - super(i1, i2, e1); - // Send close signal - i2.closeContainer(e1); - } - - @Override - public void b(EntityHuman entityHuman) { - // Don't send close signal twice, might screw up - PlayerInventory playerinventory = entityHuman.inventory; - - if (playerinventory.getCarried() != null) { - ItemStack carried = playerinventory.getCarried(); - playerinventory.setCarried(null); - entityHuman.drop(carried, false); - } - } - -} diff --git a/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java b/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java index 773f1f9..f6dae14 100644 --- a/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java +++ b/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/AnySilentContainer.java @@ -1,33 +1,35 @@ /* * Copyright (C) 2011-2014 lishid. All rights reserved. - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_8_R2; +import java.lang.reflect.Field; + import com.lishid.openinv.internal.IAnySilentContainer; -import org.bukkit.ChatColor; +import net.minecraft.server.v1_8_R2.WorldSettings; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryView; import net.minecraft.server.v1_8_R2.AxisAlignedBB; import net.minecraft.server.v1_8_R2.Block; import net.minecraft.server.v1_8_R2.BlockChest; import net.minecraft.server.v1_8_R2.BlockEnderChest; import net.minecraft.server.v1_8_R2.BlockPosition; -import net.minecraft.server.v1_8_R2.Container; import net.minecraft.server.v1_8_R2.Entity; import net.minecraft.server.v1_8_R2.EntityOcelot; import net.minecraft.server.v1_8_R2.EntityPlayer; @@ -35,17 +37,28 @@ import net.minecraft.server.v1_8_R2.EnumDirection; import net.minecraft.server.v1_8_R2.ITileInventory; import net.minecraft.server.v1_8_R2.InventoryEnderChest; import net.minecraft.server.v1_8_R2.InventoryLargeChest; -import net.minecraft.server.v1_8_R2.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_8_R2.PlayerInteractManager; import net.minecraft.server.v1_8_R2.StatisticList; import net.minecraft.server.v1_8_R2.TileEntity; import net.minecraft.server.v1_8_R2.TileEntityChest; import net.minecraft.server.v1_8_R2.TileEntityEnderChest; import net.minecraft.server.v1_8_R2.World; - -import org.bukkit.craftbukkit.v1_8_R2.event.CraftEventFactory; +import net.minecraft.server.v1_8_R2.WorldSettings.EnumGamemode; public class AnySilentContainer implements IAnySilentContainer { + private Field playerInteractManagerGamemode; + + public AnySilentContainer() { + try { + this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); + this.playerInteractManagerGamemode.setAccessible(true); + } catch (Exception e) { + System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); + e.printStackTrace(); + } + } + @Override public boolean isAnySilentContainer(org.bukkit.block.Block block) { return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; @@ -144,7 +157,6 @@ public class AnySilentContainer implements IAnySilentContainer { ITileInventory tileInventory = (ITileInventory) tile; Block block = world.getType(blockPosition).getBlock(); - Container container = null; if (block instanceof BlockChest) { for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { @@ -176,42 +188,64 @@ public class AnySilentContainer implements IAnySilentContainer { } else if (blockChest.b == 1) { player.b(StatisticList.U); } - - if (silentchest) { - container = new SilentContainerChest(player.inventory, tileInventory, player); - } } - // AnyChest only - SilentChest not active or container unsupported - if (!silentchest || container == null) { + // AnyChest only - SilentChest not active, container unsupported, or unnecessary. + if (!silentchest || player.playerInteractManager.getGameMode() == WorldSettings.EnumGamemode.SPECTATOR) { player.openContainer(tileInventory); return true; } - // SilentChest - try { - // Call InventoryOpenEvent - container = CraftEventFactory.callInventoryOpenEvent(player, container, false); - if (container == null) { - return false; - } - - // Open window - int windowId = player.nextContainerCounter(); - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, tileInventory.getContainerName(), tileInventory.getScoreboardDisplayName(), tileInventory.getSize())); - player.activeContainer = container; - player.activeContainer.windowId = windowId; - player.activeContainer.addSlotListener(player); - - return true; - } catch (Exception e) { - e.printStackTrace(); - p.sendMessage(ChatColor.RED + "Error while sending silent container."); + // SilentChest requires access to setting players' gamemode directly. + if (this.playerInteractManagerGamemode == null) { return false; } + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.openContainer(tileInventory); + this.forceGameMode(player, gamemode); + return true; } @Override - public void deactivateContainer(final Player bukkitPlayer) {} + public void deactivateContainer(final Player bukkitPlayer) { + if (this.playerInteractManagerGamemode == null) { + return; + } + + InventoryView view = bukkitPlayer.getOpenInventory(); + switch (view.getType()) { + case CHEST: + case ENDER_CHEST: + break; + default: + return; + } + + EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.activeContainer.b(player); + player.activeContainer = player.defaultContainer; + this.forceGameMode(player, gamemode); + } + + private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { + if (this.playerInteractManagerGamemode == null) { + // No need to warn repeatedly, error on startup and lack of function should be enough. + return; + } + try { + if (!this.playerInteractManagerGamemode.isAccessible()) { + // Just in case, ensure accessible. + this.playerInteractManagerGamemode.setAccessible(true); + } + this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java b/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java deleted file mode 100644 index 066f771..0000000 --- a/internal/v1_8_R2/src/main/java/com/lishid/openinv/internal/v1_8_R2/SilentContainerChest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2014 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_8_R2; - -import net.minecraft.server.v1_8_R2.ContainerChest; -import net.minecraft.server.v1_8_R2.EntityHuman; -import net.minecraft.server.v1_8_R2.IInventory; -import net.minecraft.server.v1_8_R2.ItemStack; -import net.minecraft.server.v1_8_R2.PlayerInventory; - -public class SilentContainerChest extends ContainerChest { - - public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { - super(i1, i2, e1); - // Send close signal - i2.closeContainer(e1); - } - - @Override - public void b(EntityHuman entityHuman) { - // Don't send close signal twice, might screw up - PlayerInventory playerinventory = entityHuman.inventory; - - if (playerinventory.getCarried() != null) { - ItemStack carried = playerinventory.getCarried(); - playerinventory.setCarried(null); - entityHuman.drop(carried, false); - } - } - -} diff --git a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java index 3789042..7310cf0 100644 --- a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java +++ b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/AnySilentContainer.java @@ -1,33 +1,34 @@ /* * Copyright (C) 2011-2014 lishid. All rights reserved. - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_8_R3; +import java.lang.reflect.Field; + import com.lishid.openinv.internal.IAnySilentContainer; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryView; import net.minecraft.server.v1_8_R3.AxisAlignedBB; import net.minecraft.server.v1_8_R3.Block; import net.minecraft.server.v1_8_R3.BlockChest; import net.minecraft.server.v1_8_R3.BlockEnderChest; import net.minecraft.server.v1_8_R3.BlockPosition; -import net.minecraft.server.v1_8_R3.Container; import net.minecraft.server.v1_8_R3.Entity; import net.minecraft.server.v1_8_R3.EntityOcelot; import net.minecraft.server.v1_8_R3.EntityPlayer; @@ -35,17 +36,28 @@ import net.minecraft.server.v1_8_R3.EnumDirection; import net.minecraft.server.v1_8_R3.ITileInventory; import net.minecraft.server.v1_8_R3.InventoryEnderChest; import net.minecraft.server.v1_8_R3.InventoryLargeChest; -import net.minecraft.server.v1_8_R3.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_8_R3.PlayerInteractManager; import net.minecraft.server.v1_8_R3.StatisticList; import net.minecraft.server.v1_8_R3.TileEntity; import net.minecraft.server.v1_8_R3.TileEntityChest; import net.minecraft.server.v1_8_R3.TileEntityEnderChest; import net.minecraft.server.v1_8_R3.World; - -import org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory; +import net.minecraft.server.v1_8_R3.WorldSettings.EnumGamemode; public class AnySilentContainer implements IAnySilentContainer { + private Field playerInteractManagerGamemode; + + public AnySilentContainer() { + try { + this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); + this.playerInteractManagerGamemode.setAccessible(true); + } catch (Exception e) { + System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); + e.printStackTrace(); + } + } + @Override public boolean isAnySilentContainer(org.bukkit.block.Block block) { return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; @@ -144,7 +156,6 @@ public class AnySilentContainer implements IAnySilentContainer { ITileInventory tileInventory = (ITileInventory) tile; Block block = world.getType(blockPosition).getBlock(); - Container container = null; if (block instanceof BlockChest) { for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { @@ -176,42 +187,64 @@ public class AnySilentContainer implements IAnySilentContainer { } else if (blockChest.b == 1) { player.b(StatisticList.U); } - - if (silentchest) { - container = new SilentContainerChest(player.inventory, tileInventory, player); - } } - // AnyChest only - SilentChest not active or container unsupported - if (!silentchest || container == null) { + // AnyChest only - SilentChest not active, container unsupported, or unnecessary. + if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { player.openContainer(tileInventory); return true; } - // SilentChest - try { - // Call InventoryOpenEvent - container = CraftEventFactory.callInventoryOpenEvent(player, container, false); - if (container == null) { - return false; - } - - // Open window - int windowId = player.nextContainerCounter(); - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, tileInventory.getContainerName(), tileInventory.getScoreboardDisplayName(), tileInventory.getSize())); - player.activeContainer = container; - player.activeContainer.windowId = windowId; - player.activeContainer.addSlotListener(player); - - return true; - } catch (Exception e) { - e.printStackTrace(); - p.sendMessage(ChatColor.RED + "Error while sending silent container."); + // SilentChest requires access to setting players' gamemode directly. + if (this.playerInteractManagerGamemode == null) { return false; } + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.openContainer(tileInventory); + this.forceGameMode(player, gamemode); + return true; } @Override - public void deactivateContainer(final Player bukkitPlayer) {} + public void deactivateContainer(final Player bukkitPlayer) { + if (this.playerInteractManagerGamemode == null) { + return; + } + + InventoryView view = bukkitPlayer.getOpenInventory(); + switch (view.getType()) { + case CHEST: + case ENDER_CHEST: + break; + default: + return; + } + + EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.activeContainer.b(player); + player.activeContainer = player.defaultContainer; + this.forceGameMode(player, gamemode); + } + + private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { + if (this.playerInteractManagerGamemode == null) { + // No need to warn repeatedly, error on startup and lack of function should be enough. + return; + } + try { + if (!this.playerInteractManagerGamemode.isAccessible()) { + // Just in case, ensure accessible. + this.playerInteractManagerGamemode.setAccessible(true); + } + this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java b/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java deleted file mode 100644 index ef20562..0000000 --- a/internal/v1_8_R3/src/main/java/com/lishid/openinv/internal/v1_8_R3/SilentContainerChest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2014 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_8_R3; - -import net.minecraft.server.v1_8_R3.ContainerChest; -import net.minecraft.server.v1_8_R3.EntityHuman; -import net.minecraft.server.v1_8_R3.IInventory; -import net.minecraft.server.v1_8_R3.ItemStack; -import net.minecraft.server.v1_8_R3.PlayerInventory; - -public class SilentContainerChest extends ContainerChest { - - public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { - super(i1, i2, e1); - // close signal - i2.closeContainer(e1); - } - - @Override - public void b(EntityHuman entityHuman) { - // Don't send close signal twice, might screw up - PlayerInventory playerinventory = entityHuman.inventory; - - if (playerinventory.getCarried() != null) { - ItemStack carried = playerinventory.getCarried(); - playerinventory.setCarried(null); - entityHuman.drop(carried, false); - } - } - -} diff --git a/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java b/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java index e4e26c8..0c27d4c 100644 --- a/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java +++ b/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/AnySilentContainer.java @@ -1,33 +1,34 @@ /* * Copyright (C) 2011-2014 lishid. All rights reserved. - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_9_R1; +import java.lang.reflect.Field; + import com.lishid.openinv.internal.IAnySilentContainer; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryView; import net.minecraft.server.v1_9_R1.AxisAlignedBB; import net.minecraft.server.v1_9_R1.Block; import net.minecraft.server.v1_9_R1.BlockChest; import net.minecraft.server.v1_9_R1.BlockEnderChest; import net.minecraft.server.v1_9_R1.BlockPosition; -import net.minecraft.server.v1_9_R1.Container; import net.minecraft.server.v1_9_R1.Entity; import net.minecraft.server.v1_9_R1.EntityOcelot; import net.minecraft.server.v1_9_R1.EntityPlayer; @@ -35,17 +36,28 @@ import net.minecraft.server.v1_9_R1.EnumDirection; import net.minecraft.server.v1_9_R1.ITileInventory; import net.minecraft.server.v1_9_R1.InventoryEnderChest; import net.minecraft.server.v1_9_R1.InventoryLargeChest; -import net.minecraft.server.v1_9_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_9_R1.PlayerInteractManager; import net.minecraft.server.v1_9_R1.StatisticList; import net.minecraft.server.v1_9_R1.TileEntity; import net.minecraft.server.v1_9_R1.TileEntityChest; import net.minecraft.server.v1_9_R1.TileEntityEnderChest; import net.minecraft.server.v1_9_R1.World; - -import org.bukkit.craftbukkit.v1_9_R1.event.CraftEventFactory; +import net.minecraft.server.v1_9_R1.WorldSettings.EnumGamemode; public class AnySilentContainer implements IAnySilentContainer { + private Field playerInteractManagerGamemode; + + public AnySilentContainer() { + try { + this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); + this.playerInteractManagerGamemode.setAccessible(true); + } catch (Exception e) { + System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); + e.printStackTrace(); + } + } + @Override public boolean isAnySilentContainer(org.bukkit.block.Block block) { return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; @@ -144,7 +156,6 @@ public class AnySilentContainer implements IAnySilentContainer { ITileInventory tileInventory = (ITileInventory) tile; Block block = world.getType(blockPosition).getBlock(); - Container container = null; if (block instanceof BlockChest) { for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { @@ -176,42 +187,64 @@ public class AnySilentContainer implements IAnySilentContainer { } else if (blockChest.g == BlockChest.Type.TRAP) { player.b(StatisticList.W); } - - if (silentchest) { - container = new SilentContainerChest(player.inventory, tileInventory, player); - } } - // AnyChest only - SilentChest not active or container unsupported - if (!silentchest || container == null) { + // AnyChest only - SilentChest not active, container unsupported, or unnecessary. + if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { player.openContainer(tileInventory); return true; } - // SilentChest - try { - // Call InventoryOpenEvent - container = CraftEventFactory.callInventoryOpenEvent(player, container, false); - if (container == null) { - return false; - } - - // Open window - int windowId = player.nextContainerCounter(); - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, tileInventory.getContainerName(), tileInventory.getScoreboardDisplayName(), tileInventory.getSize())); - player.activeContainer = container; - player.activeContainer.windowId = windowId; - player.activeContainer.addSlotListener(player); - - return true; - } catch (Exception e) { - e.printStackTrace(); - p.sendMessage(ChatColor.RED + "Error while sending silent container."); + // SilentChest requires access to setting players' gamemode directly. + if (this.playerInteractManagerGamemode == null) { return false; } + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.openContainer(tileInventory); + this.forceGameMode(player, gamemode); + return true; } @Override - public void deactivateContainer(final Player bukkitPlayer) {} + public void deactivateContainer(final Player bukkitPlayer) { + if (this.playerInteractManagerGamemode == null) { + return; + } + + InventoryView view = bukkitPlayer.getOpenInventory(); + switch (view.getType()) { + case CHEST: + case ENDER_CHEST: + break; + default: + return; + } + + EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.activeContainer.b(player); + player.activeContainer = player.defaultContainer; + this.forceGameMode(player, gamemode); + } + + private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { + if (this.playerInteractManagerGamemode == null) { + // No need to warn repeatedly, error on startup and lack of function should be enough. + return; + } + try { + if (!this.playerInteractManagerGamemode.isAccessible()) { + // Just in case, ensure accessible. + this.playerInteractManagerGamemode.setAccessible(true); + } + this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java b/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java deleted file mode 100644 index fa11826..0000000 --- a/internal/v1_9_R1/src/main/java/com/lishid/openinv/internal/v1_9_R1/SilentContainerChest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2014 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_9_R1; - -import net.minecraft.server.v1_9_R1.ContainerChest; -import net.minecraft.server.v1_9_R1.EntityHuman; -import net.minecraft.server.v1_9_R1.IInventory; -import net.minecraft.server.v1_9_R1.ItemStack; -import net.minecraft.server.v1_9_R1.PlayerInventory; - -public class SilentContainerChest extends ContainerChest { - - public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { - super(i1, i2, e1); - // Send close signal - i2.closeContainer(e1); - } - - @Override - public void b(EntityHuman entityHuman) { - // Don't send close signal twice, might screw up - PlayerInventory playerinventory = entityHuman.inventory; - - if (playerinventory.getCarried() != null) { - ItemStack carried = playerinventory.getCarried(); - playerinventory.setCarried(null); - entityHuman.drop(carried, false); - } - } - -} diff --git a/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java b/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java index 430f179..42f6647 100644 --- a/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java +++ b/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/AnySilentContainer.java @@ -1,33 +1,34 @@ /* * Copyright (C) 2011-2014 lishid. All rights reserved. - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.lishid.openinv.internal.v1_9_R2; +import java.lang.reflect.Field; + import com.lishid.openinv.internal.IAnySilentContainer; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryView; import net.minecraft.server.v1_9_R2.AxisAlignedBB; import net.minecraft.server.v1_9_R2.Block; import net.minecraft.server.v1_9_R2.BlockChest; import net.minecraft.server.v1_9_R2.BlockEnderChest; import net.minecraft.server.v1_9_R2.BlockPosition; -import net.minecraft.server.v1_9_R2.Container; import net.minecraft.server.v1_9_R2.Entity; import net.minecraft.server.v1_9_R2.EntityOcelot; import net.minecraft.server.v1_9_R2.EntityPlayer; @@ -35,17 +36,28 @@ import net.minecraft.server.v1_9_R2.EnumDirection; import net.minecraft.server.v1_9_R2.ITileInventory; import net.minecraft.server.v1_9_R2.InventoryEnderChest; import net.minecraft.server.v1_9_R2.InventoryLargeChest; -import net.minecraft.server.v1_9_R2.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_9_R2.PlayerInteractManager; import net.minecraft.server.v1_9_R2.StatisticList; import net.minecraft.server.v1_9_R2.TileEntity; import net.minecraft.server.v1_9_R2.TileEntityChest; import net.minecraft.server.v1_9_R2.TileEntityEnderChest; import net.minecraft.server.v1_9_R2.World; - -import org.bukkit.craftbukkit.v1_9_R2.event.CraftEventFactory; +import net.minecraft.server.v1_9_R2.WorldSettings.EnumGamemode; public class AnySilentContainer implements IAnySilentContainer { + private Field playerInteractManagerGamemode; + + public AnySilentContainer() { + try { + this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode"); + this.playerInteractManagerGamemode.setAccessible(true); + } catch (Exception e) { + System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail."); + e.printStackTrace(); + } + } + @Override public boolean isAnySilentContainer(org.bukkit.block.Block block) { return block.getType() == Material.ENDER_CHEST || block.getState() instanceof org.bukkit.block.Chest; @@ -144,7 +156,6 @@ public class AnySilentContainer implements IAnySilentContainer { ITileInventory tileInventory = (ITileInventory) tile; Block block = world.getType(blockPosition).getBlock(); - Container container = null; if (block instanceof BlockChest) { for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { @@ -176,42 +187,64 @@ public class AnySilentContainer implements IAnySilentContainer { } else if (blockChest.g == BlockChest.Type.TRAP) { player.b(StatisticList.W); } - - if (silentchest) { - container = new SilentContainerChest(player.inventory, tileInventory, player); - } } - // AnyChest only - SilentChest not active or container unsupported - if (!silentchest || container == null) { + // AnyChest only - SilentChest not active, container unsupported, or unnecessary. + if (!silentchest || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) { player.openContainer(tileInventory); return true; } - // SilentChest - try { - // Call InventoryOpenEvent - container = CraftEventFactory.callInventoryOpenEvent(player, container, false); - if (container == null) { - return false; - } - - // Open window - int windowId = player.nextContainerCounter(); - player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, tileInventory.getContainerName(), tileInventory.getScoreboardDisplayName(), tileInventory.getSize())); - player.activeContainer = container; - player.activeContainer.windowId = windowId; - player.activeContainer.addSlotListener(player); - - return true; - } catch (Exception e) { - e.printStackTrace(); - p.sendMessage(ChatColor.RED + "Error while sending silent container."); + // SilentChest requires access to setting players' gamemode directly. + if (this.playerInteractManagerGamemode == null) { return false; } + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.openContainer(tileInventory); + this.forceGameMode(player, gamemode); + return true; } @Override - public void deactivateContainer(final Player bukkitPlayer) {} + public void deactivateContainer(final Player bukkitPlayer) { + if (this.playerInteractManagerGamemode == null) { + return; + } + + InventoryView view = bukkitPlayer.getOpenInventory(); + switch (view.getType()) { + case CHEST: + case ENDER_CHEST: + break; + default: + return; + } + + EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer); + + EnumGamemode gamemode = player.playerInteractManager.getGameMode(); + this.forceGameMode(player, EnumGamemode.SPECTATOR); + player.activeContainer.b(player); + player.activeContainer = player.defaultContainer; + this.forceGameMode(player, gamemode); + } + + private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) { + if (this.playerInteractManagerGamemode == null) { + // No need to warn repeatedly, error on startup and lack of function should be enough. + return; + } + try { + if (!this.playerInteractManagerGamemode.isAccessible()) { + // Just in case, ensure accessible. + this.playerInteractManagerGamemode.setAccessible(true); + } + this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java b/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java deleted file mode 100644 index f08ecb8..0000000 --- a/internal/v1_9_R2/src/main/java/com/lishid/openinv/internal/v1_9_R2/SilentContainerChest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2014 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_9_R2; - -import net.minecraft.server.v1_9_R2.ContainerChest; -import net.minecraft.server.v1_9_R2.EntityHuman; -import net.minecraft.server.v1_9_R2.IInventory; -import net.minecraft.server.v1_9_R2.ItemStack; -import net.minecraft.server.v1_9_R2.PlayerInventory; - -public class SilentContainerChest extends ContainerChest { - - public SilentContainerChest(IInventory i1, IInventory i2, EntityHuman e1) { - super(i1, i2, e1); - // Send close signal - i2.closeContainer(e1); - } - - @Override - public void b(EntityHuman entityHuman) { - // Don't send close signal twice, might screw up - PlayerInventory playerinventory = entityHuman.inventory; - - if (playerinventory.getCarried() != null) { - ItemStack carried = playerinventory.getCarried(); - playerinventory.setCarried(null); - entityHuman.drop(carried, false); - } - } - -}