Almost entirely functional silent shulker boxes

For whatever reason, the shulker box EnumDirection isn't being retrieved properly, so AnyChest will only trigger on shulker boxes that would not be able to open if placed downwards (opening upwards). Silentchest and anychest will work, though.
Suppressed a few deprecation warnings that don't make sense to keep.
If you do use my fork of OpenInv's API, it's not yet stable (specifically, IAnySilentContainer), and will change a little more as I polish things up.
This commit is contained in:
Jikoo
2016-11-23 21:57:05 -05:00
parent 454467c20e
commit fcc9a4c0cb
8 changed files with 73 additions and 46 deletions

View File

@@ -9,7 +9,7 @@
<artifactId>openinv</artifactId> <artifactId>openinv</artifactId>
<name>OpenInv</name> <name>OpenInv</name>
<version>2.5.3-SNAPSHOT</version> <version>2.5.4</version>
<profiles> <profiles>

View File

@@ -25,7 +25,7 @@ import org.bukkit.entity.Player;
public interface IAnySilentChest { public interface IAnySilentChest {
/** /**
* @deprecated Use {@link IAnySilentContainer#activateContainer(Player, boolean, boolean, int, int, int)}. * @deprecated Use {@link IAnySilentContainer#activateContainer(Player, boolean, int, int, int)}.
*/ */
@Deprecated @Deprecated
public boolean activateChest(Player player, boolean anychest, boolean silentchest, int x, int y, int z); public boolean activateChest(Player player, boolean anychest, boolean silentchest, int x, int y, int z);

View File

@@ -3,6 +3,7 @@ package com.lishid.openinv.internal;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@SuppressWarnings("deprecation")
public interface IAnySilentContainer extends IAnySilentChest { public interface IAnySilentContainer extends IAnySilentChest {
/** /**

View File

@@ -18,16 +18,19 @@ package com.lishid.openinv.internal.v1_11_R1;
import com.lishid.openinv.internal.IAnySilentContainer; import com.lishid.openinv.internal.IAnySilentContainer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
// Volatile // Volatile
import net.minecraft.server.v1_11_R1.AxisAlignedBB; import net.minecraft.server.v1_11_R1.AxisAlignedBB;
import net.minecraft.server.v1_11_R1.Block; import net.minecraft.server.v1_11_R1.Block;
import net.minecraft.server.v1_11_R1.BlockChest; import net.minecraft.server.v1_11_R1.BlockChest;
import net.minecraft.server.v1_11_R1.BlockChest.Type; import net.minecraft.server.v1_11_R1.BlockChest.Type;
import net.minecraft.server.v1_11_R1.BlockEnderChest;
import net.minecraft.server.v1_11_R1.BlockPosition; import net.minecraft.server.v1_11_R1.BlockPosition;
import net.minecraft.server.v1_11_R1.BlockShulkerBox; import net.minecraft.server.v1_11_R1.BlockShulkerBox;
import net.minecraft.server.v1_11_R1.Container; import net.minecraft.server.v1_11_R1.Container;
@@ -62,16 +65,22 @@ public class AnySilentContainer implements IAnySilentContainer {
@Override @Override
public boolean activateContainer(Player p, boolean silentchest, int x, int y, int z) { public boolean activateContainer(Player p, boolean silentchest, int x, int y, int z) {
// TODO backport to all modules? TODO change new API to activateContainer(Player, Block)? Use BlockState instead?
if (silentchest && p.getWorld().getBlockAt(x, y, z).getType() == Material.ENDER_CHEST) {
p.openInventory(p.getEnderChest());
return true;
}
EntityPlayer player = ((CraftPlayer) p).getHandle(); EntityPlayer player = ((CraftPlayer) p).getHandle();
World world = player.world; final World world = player.world;
BlockPosition blockPosition = new BlockPosition(x, y, z); final BlockPosition blockPosition = new BlockPosition(x, y, z);
Object tile = world.getTileEntity(blockPosition); Object tile = world.getTileEntity(blockPosition);
if (tile == null) { if (tile == null) {
return false; return false;
} }
Block block = world.getType(new BlockPosition(x, y, z)).getBlock(); Block block = world.getType(blockPosition).getBlock();
Container container = null; Container container = null;
if (block instanceof BlockChest) { if (block instanceof BlockChest) {
@@ -115,41 +124,56 @@ public class AnySilentContainer implements IAnySilentContainer {
player.b(StatisticList.ae); player.b(StatisticList.ae);
if (silentchest && tile instanceof TileEntityShulkerBox) { if (silentchest && tile instanceof TileEntityShulkerBox) {
// TODO: End state allows for silent opening by other players while open (not close) // Set value to current + 1. Ensures consistency later when resetting.
// increases by 1 when animation is scheduled to complete, even though animation does not occur SilentContainerShulkerBox.setOpenValue((TileEntityShulkerBox) tile,
// Can't set value lower than 0, it corrects. SilentContainerShulkerBox.getOpenValue((TileEntityShulkerBox) tile) + 1);
// Could schedule a reset for a couple seconds later when the animation finishes.
// Could say "that's good enough" and get some rest
int value = SilentContainerShulkerBox.getOpenValue((TileEntityShulkerBox) tile);
if (value < 1) {
SilentContainerShulkerBox.setOpenValue((TileEntityShulkerBox) tile, 2);
}
container = new SilentContainerShulkerBox(player.inventory, (IInventory) tile, player); container = new SilentContainerShulkerBox(player.inventory, (IInventory) tile, player);
// Reset value to start
SilentContainerShulkerBox.setOpenValue((TileEntityShulkerBox) tile, value);
} }
} }
if (!(tile instanceof IInventory)) {
// TODO anyenderchest
p.sendMessage(ChatColor.RED + "Unhandled non-IInventory for block!");
return false;
}
boolean returnValue = false; boolean returnValue = false;
final IInventory iInventory = (IInventory) tile;
if (!silentchest || container == null) { if (!silentchest || container == null) {
player.openContainer((IInventory) tile); player.openContainer(iInventory);
returnValue = true; returnValue = true;
} else { } else {
try { try {
int windowId = player.nextContainerCounter(); int windowId = player.nextContainerCounter();
player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, "minecraft:chest", ((IInventory) tile).getScoreboardDisplayName(), ((IInventory) tile).getSize())); player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, iInventory.getName(), iInventory.getScoreboardDisplayName(), iInventory.getSize()));
player.activeContainer = container; player.activeContainer = container;
player.activeContainer.windowId = windowId; player.activeContainer.windowId = windowId;
player.activeContainer.addSlotListener(player); player.activeContainer.addSlotListener(player);
returnValue = true; returnValue = true;
if (tile instanceof TileEntityShulkerBox) {
new BukkitRunnable() {
@Override
public void run() {
// TODO hacky
Object tile = world.getTileEntity(blockPosition);
if (!(tile instanceof TileEntityShulkerBox)) {
return;
}
TileEntityShulkerBox box = (TileEntityShulkerBox) tile;
// Reset back - we added 1, and calling TileEntityShulkerBox#startOpen adds 1 more.
SilentContainerShulkerBox.setOpenValue(box,
SilentContainerShulkerBox.getOpenValue((TileEntityShulkerBox) tile) - 2);
}
}.runTaskLater(Bukkit.getPluginManager().getPlugin("OpenInv"), 2);
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
p.sendMessage(ChatColor.RED + "Error while sending silent chest."); p.sendMessage(ChatColor.RED + "Error while sending silent chest.");
} }
} }
return returnValue; return returnValue;
} }
@@ -164,16 +188,31 @@ public class AnySilentContainer implements IAnySilentContainer {
return isBlockedShulkerBox(world, blockPosition, block); return isBlockedShulkerBox(world, blockPosition, block);
} }
// For reference, loot at net.minecraft.server.BlockChest if (block instanceof BlockEnderChest) {
// Ender chests are not blocked by ocelots.
return world.getType(new BlockPosition(x, y + 1, z)).m();
}
// Check if chest is blocked or has an ocelot on top // Check if chest is blocked or has an ocelot on top
if (world.getType(new BlockPosition(x, y + 1, z)).m() || hasOcelotOnTop(world, blockPosition)) { if (isBlockedChest(world, blockPosition)) {
return true; return true;
} }
// Check for matching adjacent chests that are blocked or have an ocelot on top // Check for matching adjacent chests that are blocked or have an ocelot on top
for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) { for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) {
BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection); BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection);
if (isBlockedChest(world, block, localBlockPosition)) { Block localBlock = world.getType(localBlockPosition).getBlock();
if (localBlock != block) {
continue;
}
TileEntity localTileEntity = world.getTileEntity(localBlockPosition);
if (!(localTileEntity instanceof TileEntityChest)) {
continue;
}
if (isBlockedChest(world, localBlockPosition)) {
return true; return true;
} }
} }
@@ -198,17 +237,14 @@ public class AnySilentContainer implements IAnySilentContainer {
.a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(), .a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(),
enumDirection.getAdjacentZ()); enumDirection.getAdjacentZ());
return !(world.b(axisAlignedBB.a(blockPosition.shift(enumDirection)))); return world.b(axisAlignedBB.a(blockPosition.shift(enumDirection)));
} }
return true;
}
private boolean isBlockedChest(World world, Block block, BlockPosition blockPosition) {
if (world.getType(blockPosition).getBlock() == block) {
return false; return false;
} }
private boolean isBlockedChest(World world, BlockPosition blockPosition) {
// For reference, loot at net.minecraft.server.BlockChest
return world.getType(blockPosition.up()).m() || hasOcelotOnTop(world, blockPosition); return world.getType(blockPosition.up()).m() || hasOcelotOnTop(world, blockPosition);
} }

View File

@@ -38,24 +38,13 @@ public class SilentContainerShulkerBox extends ContainerShulkerBox {
} }
} }
private final TileEntityShulkerBox tile;
public SilentContainerShulkerBox(PlayerInventory playerInventory, IInventory iInventory, public SilentContainerShulkerBox(PlayerInventory playerInventory, IInventory iInventory,
EntityHuman entityHuman) { EntityHuman entityHuman) {
super(playerInventory, iInventory, entityHuman); super(playerInventory, iInventory, entityHuman);
if (iInventory instanceof TileEntityShulkerBox) {
tile = (TileEntityShulkerBox) iInventory;
} else {
tile = null;
}
} }
@Override @Override
public void b(EntityHuman entityHuman) { public void b(EntityHuman entityHuman) {
if (tile != null) {
setOpenValue(tile, tile.getViewers().size());
}
PlayerInventory playerinventory = entityHuman.inventory; PlayerInventory playerinventory = entityHuman.inventory;
if (!playerinventory.getCarried().isEmpty()) { if (!playerinventory.getCarried().isEmpty()) {

View File

@@ -30,6 +30,7 @@ import net.minecraft.util.com.mojang.authlib.GameProfile;
import org.bukkit.craftbukkit.v1_7_R2.CraftServer; import org.bukkit.craftbukkit.v1_7_R2.CraftServer;
@SuppressWarnings("deprecation") // Deprecated methods are used properly and will not change.
public class PlayerDataManager implements IPlayerDataManager { public class PlayerDataManager implements IPlayerDataManager {
@Override @Override

View File

@@ -107,7 +107,7 @@ public class OpenInv extends JavaPlugin {
accessor = new InternalAccessor(this); accessor = new InternalAccessor(this);
// Version check // Version check
if (!accessor.initialize(getServer())) { if (!accessor.initialize(getServer())) {
getLogger().info("Your version of CraftBukkit (" + accessor.getVersion() + ")is not supported."); getLogger().info("Your version of CraftBukkit (" + accessor.getVersion() + ") is not supported.");
getLogger().info("Please look for an updated version of OpenInv."); getLogger().info("Please look for an updated version of OpenInv.");
pm.disablePlugin(this); pm.disablePlugin(this);
return; return;

View File

@@ -10,30 +10,30 @@ commands:
aliases: [oi, inv, open] aliases: [oi, inv, open]
description: Open a player's inventory description: Open a player's inventory
permission: OpenInv.*;OpenInv.openinv permission: OpenInv.*;OpenInv.openinv
usage: | usage: |-
/<command> - Open last person's inventory /<command> - Open last person's inventory
/<command> <Player> - Open a player's inventory /<command> <Player> - Open a player's inventory
openender: openender:
aliases: [oe] aliases: [oe]
description: Opens the enderchest of a player description: Opens the enderchest of a player
permission: OpenInv.*;OpenInv.openender permission: OpenInv.*;OpenInv.openender
usage: | usage: |-
/<command> <Player> - Opens a player's enderchest /<command> <Player> - Opens a player's enderchest
searchinv: searchinv:
aliases: [si] aliases: [si]
description: Search and list players having a specific item description: Search and list players having a specific item
permission: OpenInv.*;OpenInv.search permission: OpenInv.*;OpenInv.search
usage: | usage: |-
/<command> <Item> [MinAmount] - Item can be the Item ID or the CraftBukkit Item Name, MinAmount is the minimum amount to be considered. /<command> <Item> [MinAmount] - Item can be the Item ID or the CraftBukkit Item Name, MinAmount is the minimum amount to be considered.
silentchest: silentchest:
aliases: [sc, silent] aliases: [sc, silent]
description: Toggle silent chest function, which hides the animation of a chest when opened or closed, and suppresses the sound. description: Toggle silent chest function, which hides the animation of a chest when opened or closed, and suppresses the sound.
permission: OpenInv.*;OpenInv.silent permission: OpenInv.*;OpenInv.silent
usage: | usage: |-
/<command> [Check] - Checks whether silent chest is enabled /<command> [Check] - Checks whether silent chest is enabled
anychest: anychest:
aliases: [ac] aliases: [ac]
description: Toggle anychest function, which allows opening of blocked chests. description: Toggle anychest function, which allows opening of blocked chests.
permission: OpenInv.*;OpenInv.anychest permission: OpenInv.*;OpenInv.anychest
usage: | usage: |-
/<command> [Check] - Checks whether anychest is enabled /<command> [Check] - Checks whether anychest is enabled