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);
- }
- }
-
-}