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:
@@ -9,7 +9,7 @@
|
||||
|
||||
<artifactId>openinv</artifactId>
|
||||
<name>OpenInv</name>
|
||||
<version>2.5.3-SNAPSHOT</version>
|
||||
<version>2.5.4</version>
|
||||
|
||||
<profiles>
|
||||
|
||||
|
@@ -25,7 +25,7 @@ import org.bukkit.entity.Player;
|
||||
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
|
||||
public boolean activateChest(Player player, boolean anychest, boolean silentchest, int x, int y, int z);
|
||||
|
@@ -3,6 +3,7 @@ package com.lishid.openinv.internal;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public interface IAnySilentContainer extends IAnySilentChest {
|
||||
|
||||
/**
|
||||
|
@@ -18,16 +18,19 @@ package com.lishid.openinv.internal.v1_11_R1;
|
||||
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
// Volatile
|
||||
import net.minecraft.server.v1_11_R1.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_11_R1.Block;
|
||||
import net.minecraft.server.v1_11_R1.BlockChest;
|
||||
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.BlockShulkerBox;
|
||||
import net.minecraft.server.v1_11_R1.Container;
|
||||
@@ -62,16 +65,22 @@ public class AnySilentContainer implements IAnySilentContainer {
|
||||
@Override
|
||||
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();
|
||||
World world = player.world;
|
||||
BlockPosition blockPosition = new BlockPosition(x, y, z);
|
||||
final World world = player.world;
|
||||
final BlockPosition blockPosition = new BlockPosition(x, y, z);
|
||||
Object tile = world.getTileEntity(blockPosition);
|
||||
|
||||
if (tile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Block block = world.getType(new BlockPosition(x, y, z)).getBlock();
|
||||
Block block = world.getType(blockPosition).getBlock();
|
||||
Container container = null;
|
||||
|
||||
if (block instanceof BlockChest) {
|
||||
@@ -115,41 +124,56 @@ public class AnySilentContainer implements IAnySilentContainer {
|
||||
player.b(StatisticList.ae);
|
||||
|
||||
if (silentchest && tile instanceof TileEntityShulkerBox) {
|
||||
// TODO: End state allows for silent opening by other players while open (not close)
|
||||
// increases by 1 when animation is scheduled to complete, even though animation does not occur
|
||||
// Can't set value lower than 0, it corrects.
|
||||
// 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);
|
||||
}
|
||||
// Set value to current + 1. Ensures consistency later when resetting.
|
||||
SilentContainerShulkerBox.setOpenValue((TileEntityShulkerBox) tile,
|
||||
SilentContainerShulkerBox.getOpenValue((TileEntityShulkerBox) tile) + 1);
|
||||
|
||||
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;
|
||||
final IInventory iInventory = (IInventory) tile;
|
||||
|
||||
if (!silentchest || container == null) {
|
||||
player.openContainer((IInventory) tile);
|
||||
player.openContainer(iInventory);
|
||||
returnValue = true;
|
||||
} else {
|
||||
try {
|
||||
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.windowId = windowId;
|
||||
player.activeContainer.addSlotListener(player);
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
p.sendMessage(ChatColor.RED + "Error while sending silent chest.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -164,16 +188,31 @@ public class AnySilentContainer implements IAnySilentContainer {
|
||||
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
|
||||
if (world.getType(new BlockPosition(x, y + 1, z)).m() || hasOcelotOnTop(world, blockPosition)) {
|
||||
if (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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -198,17 +237,14 @@ public class AnySilentContainer implements IAnySilentContainer {
|
||||
.a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(),
|
||||
enumDirection.getAdjacentZ());
|
||||
|
||||
return !(world.b(axisAlignedBB.a(blockPosition.shift(enumDirection))));
|
||||
return world.b(axisAlignedBB.a(blockPosition.shift(enumDirection)));
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBlockedChest(World world, Block block, BlockPosition blockPosition) {
|
||||
if (world.getType(blockPosition).getBlock() == block) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -38,24 +38,13 @@ public class SilentContainerShulkerBox extends ContainerShulkerBox {
|
||||
}
|
||||
}
|
||||
|
||||
private final TileEntityShulkerBox tile;
|
||||
|
||||
public SilentContainerShulkerBox(PlayerInventory playerInventory, IInventory iInventory,
|
||||
EntityHuman entityHuman) {
|
||||
super(playerInventory, iInventory, entityHuman);
|
||||
if (iInventory instanceof TileEntityShulkerBox) {
|
||||
tile = (TileEntityShulkerBox) iInventory;
|
||||
} else {
|
||||
tile = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void b(EntityHuman entityHuman) {
|
||||
if (tile != null) {
|
||||
setOpenValue(tile, tile.getViewers().size());
|
||||
}
|
||||
|
||||
PlayerInventory playerinventory = entityHuman.inventory;
|
||||
|
||||
if (!playerinventory.getCarried().isEmpty()) {
|
||||
|
@@ -30,6 +30,7 @@ import net.minecraft.util.com.mojang.authlib.GameProfile;
|
||||
|
||||
import org.bukkit.craftbukkit.v1_7_R2.CraftServer;
|
||||
|
||||
@SuppressWarnings("deprecation") // Deprecated methods are used properly and will not change.
|
||||
public class PlayerDataManager implements IPlayerDataManager {
|
||||
|
||||
@Override
|
||||
|
@@ -107,7 +107,7 @@ public class OpenInv extends JavaPlugin {
|
||||
accessor = new InternalAccessor(this);
|
||||
// Version check
|
||||
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.");
|
||||
pm.disablePlugin(this);
|
||||
return;
|
||||
|
@@ -10,30 +10,30 @@ commands:
|
||||
aliases: [oi, inv, open]
|
||||
description: Open a player's inventory
|
||||
permission: OpenInv.*;OpenInv.openinv
|
||||
usage: |
|
||||
usage: |-
|
||||
/<command> - Open last person's inventory
|
||||
/<command> <Player> - Open a player's inventory
|
||||
openender:
|
||||
aliases: [oe]
|
||||
description: Opens the enderchest of a player
|
||||
permission: OpenInv.*;OpenInv.openender
|
||||
usage: |
|
||||
usage: |-
|
||||
/<command> <Player> - Opens a player's enderchest
|
||||
searchinv:
|
||||
aliases: [si]
|
||||
description: Search and list players having a specific item
|
||||
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.
|
||||
silentchest:
|
||||
aliases: [sc, silent]
|
||||
description: Toggle silent chest function, which hides the animation of a chest when opened or closed, and suppresses the sound.
|
||||
permission: OpenInv.*;OpenInv.silent
|
||||
usage: |
|
||||
usage: |-
|
||||
/<command> [Check] - Checks whether silent chest is enabled
|
||||
anychest:
|
||||
aliases: [ac]
|
||||
description: Toggle anychest function, which allows opening of blocked chests.
|
||||
permission: OpenInv.*;OpenInv.anychest
|
||||
usage: |
|
||||
usage: |-
|
||||
/<command> [Check] - Checks whether anychest is enabled
|
||||
|
Reference in New Issue
Block a user