From 4335b8dc2cbd2aeb4e97b84ba1c9144ef457c9d1 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 25 Nov 2016 16:42:06 -0500 Subject: [PATCH] Update plugin to jikoo/master - numerous fixes and changes * Added permissions to commands in plugin.yml * Removed item wand functionality - see 3549431fbc for reasoning * Changed a lot of player loading logic * Added config option DisableSaving - see Jikoo#6 * Fixed closing SilentChest not dropping item on cursor * Added SilentChest support for shulker boxes --- .../openinv/internal/IAnySilentChest.java | 40 -- .../openinv/internal/IAnySilentContainer.java | 3 +- .../openinv/internal/IInventoryAccess.java | 34 +- .../openinv/internal/IPlayerDataManager.java | 8 - .../openinv/internal/ISpecialEnderChest.java | 12 - .../internal/ISpecialPlayerInventory.java | 12 - .../openinv/internal/InternalAccessor.java | 47 +- .../com/lishid/openinv/ConfigUpdater.java | 163 ----- .../com/lishid/openinv/Configuration.java | 153 ---- .../main/java/com/lishid/openinv/OpenInv.java | 678 +++++++++++++----- .../openinv/OpenInvInventoryListener.java | 62 ++ .../lishid/openinv/OpenInvPlayerListener.java | 78 ++ .../java/com/lishid/openinv/Permissions.java | 47 +- .../openinv/commands/AnyChestCommand.java | 72 -- .../commands/AnyChestPluginCommand.java | 54 ++ .../openinv/commands/OpenEnderCommand.java | 161 ----- .../commands/OpenEnderPluginCommand.java | 132 ++++ .../openinv/commands/OpenInvCommand.java | 156 ---- .../commands/OpenInvPluginCommand.java | 145 ++++ .../openinv/commands/SearchEnderCommand.java | 66 -- .../openinv/commands/SearchInvCommand.java | 88 --- .../commands/SearchInvPluginCommand.java | 72 ++ .../openinv/commands/SilentChestCommand.java | 72 -- .../commands/SilentChestPluginCommand.java | 53 ++ .../commands/ToggleOpenInvCommand.java | 72 -- .../listeners/OpenInvEntityListener.java | 64 -- .../listeners/OpenInvInventoryListener.java | 44 -- .../listeners/OpenInvPlayerListener.java | 178 ----- .../com/lishid/openinv/utils/UUIDFetcher.java | 108 --- .../com/lishid/openinv/utils/UUIDUtils.java | 81 --- plugin/src/main/resources/config.yml | 6 - .../internal/v1_11_R1/AnySilentChest.java | 174 ----- .../internal/v1_11_R1/AnySilentContainer.java | 276 +++++++ .../internal/v1_11_R1/EnumDirectionList.java | 25 - .../internal/v1_11_R1/InventoryAccess.java | 95 +-- .../internal/v1_11_R1/PlayerDataManager.java | 69 +- .../v1_11_R1/SilentContainerChest.java | 47 ++ .../v1_11_R1/SilentContainerShulkerBox.java | 56 ++ .../internal/v1_11_R1/SilentInventory.java | 183 ----- .../internal/v1_11_R1/SpecialEnderChest.java | 98 ++- .../v1_11_R1/SpecialPlayerInventory.java | 321 ++++----- 41 files changed, 1829 insertions(+), 2476 deletions(-) delete mode 100644 internal/src/main/java/com/lishid/openinv/internal/IAnySilentChest.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/ConfigUpdater.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/Configuration.java create mode 100644 plugin/src/main/java/com/lishid/openinv/OpenInvInventoryListener.java create mode 100644 plugin/src/main/java/com/lishid/openinv/OpenInvPlayerListener.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/AnyChestCommand.java create mode 100644 plugin/src/main/java/com/lishid/openinv/commands/AnyChestPluginCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/OpenEnderCommand.java create mode 100644 plugin/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/OpenInvCommand.java create mode 100644 plugin/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/SearchEnderCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/SearchInvCommand.java create mode 100644 plugin/src/main/java/com/lishid/openinv/commands/SearchInvPluginCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/SilentChestCommand.java create mode 100644 plugin/src/main/java/com/lishid/openinv/commands/SilentChestPluginCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/commands/ToggleOpenInvCommand.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/listeners/OpenInvEntityListener.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/listeners/OpenInvInventoryListener.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/listeners/OpenInvPlayerListener.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/utils/UUIDFetcher.java delete mode 100644 plugin/src/main/java/com/lishid/openinv/utils/UUIDUtils.java delete mode 100644 plugin/src/main/resources/config.yml delete mode 100644 v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentChest.java create mode 100644 v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentContainer.java delete mode 100644 v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/EnumDirectionList.java create mode 100644 v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerChest.java create mode 100644 v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerShulkerBox.java delete mode 100644 v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentInventory.java diff --git a/internal/src/main/java/com/lishid/openinv/internal/IAnySilentChest.java b/internal/src/main/java/com/lishid/openinv/internal/IAnySilentChest.java deleted file mode 100644 index b109b12..0000000 --- a/internal/src/main/java/com/lishid/openinv/internal/IAnySilentChest.java +++ /dev/null @@ -1,40 +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; - -import org.bukkit.block.Block; -import org.bukkit.entity.Player; - -/** - * @deprecated Use {@link IAnySilentContainer} - */ -@Deprecated -public interface IAnySilentChest { - - /** - * @deprecated Use {@link IAnySilentContainer#activateContainer(Player, boolean, Block)}. - */ - @Deprecated - public boolean activateChest(Player player, boolean anychest, boolean silentchest, int x, int y, int z); - - /** - * @deprecated Use {@link IAnySilentContainer#isAnyContainerNeeded(Player, Block)}. - */ - @Deprecated - public boolean isAnyChestNeeded(Player player, int x, int y, int z); - -} diff --git a/internal/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java b/internal/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java index a7b6802..8f97e18 100644 --- a/internal/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java +++ b/internal/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java @@ -3,8 +3,7 @@ package com.lishid.openinv.internal; import org.bukkit.block.Block; import org.bukkit.entity.Player; -@SuppressWarnings("deprecation") -public interface IAnySilentContainer extends IAnySilentChest { +public interface IAnySilentContainer { /** * Checks if the given block is a container which can be unblocked or silenced. diff --git a/internal/src/main/java/com/lishid/openinv/internal/IInventoryAccess.java b/internal/src/main/java/com/lishid/openinv/internal/IInventoryAccess.java index 16ae2a4..f48381e 100644 --- a/internal/src/main/java/com/lishid/openinv/internal/IInventoryAccess.java +++ b/internal/src/main/java/com/lishid/openinv/internal/IInventoryAccess.java @@ -16,18 +16,42 @@ package com.lishid.openinv.internal; -import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.Inventory; public interface IInventoryAccess { /** - * Check if an entity has permission to modify the contents of an inventory. + * Check if an Inventory is an ISpecialPlayerInventory implementation. * * @param inventory the Inventory - * @param player the HumanEntity - * @return true if the HumanEntity can modify the Inventory + * @return true if the Inventory is backed by an ISpecialPlayerInventory */ - public boolean check(Inventory inventory, HumanEntity player); + public boolean isSpecialPlayerInventory(Inventory inventory); + + /** + * Gets an ISpecialPlayerInventory from an Inventory or null if the Inventory is not backed by + * an ISpecialPlayerInventory. + * + * @param inventory the Inventory + * @return the ISpecialPlayerInventory or null + */ + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory); + + /** + * Check if an Inventory is an ISpecialEnderChest implementation. + * + * @param inventory the Inventory + * @return true if the Inventory is backed by an ISpecialEnderChest + */ + public boolean isSpecialEnderChest(Inventory inventory); + + /** + * Gets an ISpecialEnderChest from an Inventory or null if the Inventory is not backed by an + * ISpecialEnderChest. + * + * @param inventory the Inventory + * @return the ISpecialEnderChest or null + */ + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory); } diff --git a/internal/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java b/internal/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java index d9738a6..bbcd68d 100644 --- a/internal/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java +++ b/internal/src/main/java/com/lishid/openinv/internal/IPlayerDataManager.java @@ -16,8 +16,6 @@ package com.lishid.openinv.internal; -import java.util.UUID; - import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -33,12 +31,6 @@ public interface IPlayerDataManager { */ public Player loadPlayer(OfflinePlayer offline); - /** - * @deprecated use {@link #loadPlayer(OfflinePlayer)} - */ - @Deprecated - public Player loadPlayer(UUID uuid); - /** * Gets a unique identifying string for an OfflinePlayer. * diff --git a/internal/src/main/java/com/lishid/openinv/internal/ISpecialEnderChest.java b/internal/src/main/java/com/lishid/openinv/internal/ISpecialEnderChest.java index 2b7c6cd..29489e1 100644 --- a/internal/src/main/java/com/lishid/openinv/internal/ISpecialEnderChest.java +++ b/internal/src/main/java/com/lishid/openinv/internal/ISpecialEnderChest.java @@ -35,23 +35,11 @@ public interface ISpecialEnderChest { */ public void setPlayerOnline(Player player); - /** - * @deprecated use {@link #setPlayerOnline(Player)} - */ - @Deprecated - public void playerOnline(Player player); - /** * Sets the Player associated with this ISpecialEnderChest offline. */ public void setPlayerOffline(); - /** - * @deprecated use {@link #setPlayerOffline()} - */ - @Deprecated - public void playerOffline(); - /** * Gets whether or not this ISpecialEnderChest is in use. * diff --git a/internal/src/main/java/com/lishid/openinv/internal/ISpecialPlayerInventory.java b/internal/src/main/java/com/lishid/openinv/internal/ISpecialPlayerInventory.java index 088ee5f..0ee9900 100644 --- a/internal/src/main/java/com/lishid/openinv/internal/ISpecialPlayerInventory.java +++ b/internal/src/main/java/com/lishid/openinv/internal/ISpecialPlayerInventory.java @@ -35,23 +35,11 @@ public interface ISpecialPlayerInventory { */ public void setPlayerOnline(Player player); - /** - * @deprecated use {@link #setPlayerOnline(Player)} - */ - @Deprecated - public void playerOnline(Player player); - /** * Sets the Player associated with this ISpecialPlayerInventory offline. */ public void setPlayerOffline(); - /** - * @deprecated use {@link #setPlayerOffline()} - */ - @Deprecated - public void playerOffline(); - /** * Gets whether or not this ISpecialPlayerInventory is in use. * diff --git a/internal/src/main/java/com/lishid/openinv/internal/InternalAccessor.java b/internal/src/main/java/com/lishid/openinv/internal/InternalAccessor.java index 01ea58d..5b4cbe5 100644 --- a/internal/src/main/java/com/lishid/openinv/internal/InternalAccessor.java +++ b/internal/src/main/java/com/lishid/openinv/internal/InternalAccessor.java @@ -17,8 +17,8 @@ package com.lishid.openinv.internal; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; -import org.bukkit.Server; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; @@ -26,30 +26,19 @@ public class InternalAccessor { private final Plugin plugin; - private String version; + private final String version; private boolean supported = false; public InternalAccessor(Plugin plugin) { this.plugin = plugin; - } - /** - * Check if the current server version is supported, and, if it is, prepare to load version-specific code. - * - * @param server the Server - * - * @return true if supported - */ - public boolean initialize(Server server) { - String packageName = server.getClass().getPackage().getName(); + String packageName = plugin.getServer().getClass().getPackage().getName(); version = packageName.substring(packageName.lastIndexOf('.') + 1); try { Class.forName("com.lishid.openinv.internal." + version + ".PlayerDataManager"); - return (supported = true); - } catch (Exception e) { - return false; - } + supported = true; + } catch (Exception e) {} } /** @@ -101,15 +90,6 @@ public class InternalAccessor { return createObject(IAnySilentContainer.class, "AnySilentContainer"); } - /** - * @deprecated Use {@link #newAnySilentContainer()} - */ - @Deprecated - public IAnySilentChest newAnySilentChest() { - IAnySilentChest iAnySilentChest = createObject(IAnySilentChest.class, "AnySilentChest"); - return iAnySilentChest != null ? iAnySilentChest : newAnySilentContainer(); - } - /** * Creates an instance of the ISpecialPlayerInventory implementation for the given Player, or * null if the current version is unsupported. @@ -180,4 +160,21 @@ public class InternalAccessor { return null; } + public static T grabFieldOfTypeFromObject(Class type, Object object) { + // Use reflection to find the iinventory + Class clazz = object.getClass(); + T result = null; + for (Field f : clazz.getDeclaredFields()) { + f.setAccessible(true); + if (type.isAssignableFrom(f.getDeclaringClass())) { + try { + result = type.cast(f.get(object)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return result; + } + } diff --git a/plugin/src/main/java/com/lishid/openinv/ConfigUpdater.java b/plugin/src/main/java/com/lishid/openinv/ConfigUpdater.java deleted file mode 100644 index cf0772c..0000000 --- a/plugin/src/main/java/com/lishid/openinv/ConfigUpdater.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.lishid.openinv; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; - -import com.lishid.openinv.utils.UUIDUtils; - -public class ConfigUpdater { - - private final OpenInv plugin; - - private static final int CONFIG_VERSION = 2; - - public ConfigUpdater(OpenInv plugin) { - this.plugin = plugin; - } - - private int getConfigVersion() { - return plugin.getConfig().getInt("config-version", 1); - } - - private boolean isConfigOutdated() { - return getConfigVersion() < CONFIG_VERSION; - } - - public void checkForUpdates() { - if (isConfigOutdated()) { - plugin.getLogger().info("[Config] Update found! Performing update..."); - performUpdate(); - } else { - plugin.getLogger().info("[Config] Update not required."); - } - } - - private void performUpdate() { - // Update according to the right version - switch (getConfigVersion()) { - case 1: - updateConfig1To2(); - break; - } - } - - private void updateConfig1To2() { - FileConfiguration config = plugin.getConfig(); - - // Backup the old config file - File configFile = new File(plugin.getDataFolder(), "config.yml"); - File oldConfigFile = new File(plugin.getDataFolder(), "config_old.yml"); - - configFile.renameTo(oldConfigFile); - - if (configFile.exists()) { - configFile.delete(); - } - - plugin.getLogger().info("[Config] Backup of old config.yml file created."); - - // Get the old config settings - int itemOpenInvItemId = config.getInt("ItemOpenInvItemID", 280); - boolean notifySilentChest = config.getBoolean("NotifySilentChest", true); - boolean notifyAnyChest = config.getBoolean("NotifyAnyChest", true); - - Map anyChestToggles = null; - Map itemOpenInvToggles = null; - Map silentChestToggles = null; - - if (config.isSet("AnyChest")) { - anyChestToggles = updateToggles("AnyChest"); - } - - if (config.isSet("ItemOpenInv")) { - itemOpenInvToggles = updateToggles("ItemOpenInv"); - } - - if (config.isSet("SilentChest")) { - silentChestToggles = updateToggles("SilentChest"); - } - - // Clear the old config - for (String key : config.getKeys(false)) { - config.set(key, null); - } - - // Set the new config options - plugin.saveDefaultConfig(); - plugin.reloadConfig(); - - config = plugin.getConfig(); // Refresh the referenced plugin config - - config.set("config-version", 2); - config.set("items.open-inv", getMaterialById(itemOpenInvItemId).toString()); - config.set("notify.any-chest", notifyAnyChest); - config.set("notify.silent-chest", notifySilentChest); - - if (anyChestToggles != null && !anyChestToggles.isEmpty()) { - for (Map.Entry entry : anyChestToggles.entrySet()) { - config.set("toggles.any-chest." + entry.getKey(), entry.getValue()); - } - } - - if (itemOpenInvToggles != null && !itemOpenInvToggles.isEmpty()) { - for (Map.Entry entry : itemOpenInvToggles.entrySet()) { - config.set("toggles.items.open-inv." + entry.getKey(), entry.getValue()); - } - } - - if (silentChestToggles != null && !silentChestToggles.isEmpty()) { - for (Map.Entry entry : silentChestToggles.entrySet()) { - config.set("toggles.silent-chest." + entry.getKey(), entry.getValue()); - } - } - - // Save the new config - plugin.saveConfig(); - plugin.getLogger().info("[Config] Update complete."); - } - - private Map updateToggles(String sectionName) { - Map toggles = new HashMap(); - - ConfigurationSection section = plugin.getConfig().getConfigurationSection(sectionName); - Set keys = section.getKeys(false); - if (keys == null || keys.isEmpty()) { - return null; - } - - int total = keys.size(); - int converted = 0; - - for (String playerName : keys) { - UUID uuid = UUIDUtils.getPlayerUUID(playerName); - - if (uuid != null) { - boolean toggled = section.getBoolean(playerName + ".toggle", false); - toggles.put(uuid, toggled); - converted++; - } - } - - plugin.getLogger().info("[Config] Converted (" + converted + "/" + total + ") " + sectionName + " toggle player usernames to UUIDs."); - - return toggles; - } - - @SuppressWarnings("deprecation") - private Material getMaterialById(int id) { - Material material = Material.getMaterial(id); - - if (material == null) { - material = Material.STICK; - } - - return material; - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/Configuration.java b/plugin/src/main/java/com/lishid/openinv/Configuration.java deleted file mode 100644 index 1a03d9a..0000000 --- a/plugin/src/main/java/com/lishid/openinv/Configuration.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.lishid.openinv; - -import org.bukkit.Material; -import org.bukkit.entity.Player; - -public class Configuration { - - private final OpenInv plugin; - - private Material openInvItem; - private boolean notifySilentChest; - private boolean notifyAnyChest; - - public Configuration(OpenInv plugin) { - this.plugin = plugin; - - // Check for config updates - ConfigUpdater configUpdater = new ConfigUpdater(plugin); - configUpdater.checkForUpdates(); - - // Load the config settings - load(); - } - - /** - * Loads OpenInv's config settings. - */ - public void load() { - // OpenInv Item - if (!plugin.getConfig().isSet("items.open-inv")) { - saveToConfig("items.open-inv", "STICK"); - } - - String itemName = plugin.getConfig().getString("items.open-inv", "STICK"); - Material material = Material.getMaterial(itemName); - - if (material == null) { - plugin.getLogger().warning("OpenInv item '" + itemName + "' does not match to a valid item. Defaulting to stick."); - material = Material.STICK; - } - - openInvItem = material; - - // Other Values - notifySilentChest = plugin.getConfig().getBoolean("notify.silent-chest", true); - notifyAnyChest = plugin.getConfig().getBoolean("notify.any-chest", true); - } - - /** - * Reloads OpenInv's config settings. - */ - public void reload() { - load(); - } - - /** - * Saves a value to the plugin config at the specified path. - * - * @param path the path to set the value to - * @param value the value to set to the path - */ - private void saveToConfig(String path, Object value) { - plugin.getConfig().set(path, value); - plugin.saveConfig(); - } - - /** - * Returns the OpenInv item Material. - * - * @return the OpenInv item Material - */ - public Material getOpenInvItem() { - return openInvItem; - } - - /** - * Returns whether or not notify silent chest is enabled. - * - * @return true if notify silent chest is enabled; false otherwise - */ - public boolean notifySilentChest() { - return notifySilentChest; - } - - /** - * Returns whether or not notify any chest is enabled. - * - * @return true if notify any chest is enabled; false otherwise - */ - public boolean notifyAnyChest() { - return notifyAnyChest; - } - - /** - * Returns a player's item OpenInv status. - * - * @param player the player to get the item OpenInv status of - * @return the player's item OpenInv status - */ - public boolean getPlayerItemOpenInvStatus(Player player) { - return plugin.getConfig().getBoolean("toggles.items.open-inv." + player.getUniqueId(), false); - } - - /** - * Returns a player's any chest status. - * - * @param player the player to get the any chest status of - * @return the player's any chest status - */ - public boolean getPlayerAnyChestStatus(Player player) { - return plugin.getConfig().getBoolean("toggles.any-chest." + player.getUniqueId(), true); - } - - /** - * Sets a player's any chest status. - * - * @param player the player to set the any chest status of - * @param status the status to set with - */ - public void setPlayerAnyChestStatus(Player player, boolean status) { - saveToConfig("toggles.any-chest." + player.getUniqueId(), status); - } - - /** - * Sets a player's item OpenInv status. - * - * @param player the player to set the item OpenInv status of - * @param status the status to set with - */ - public void setPlayerItemOpenInvStatus(Player player, boolean status) { - saveToConfig("toggles.items.open-inv." + player.getUniqueId(), status); - } - - /** - * Returns a player's silent chest status. - * - * @param player the player to get the silent chest status of - * @return the player's silent chest status - */ - public boolean getPlayerSilentChestStatus(Player player) { - return plugin.getConfig().getBoolean("toggles.silent-chest." + player.getUniqueId(), false); - } - - /** - * Sets a player's silent chest status. - * - * @param player the player to set the silent chest status of - * @param status the status to set with - */ - public void setPlayerSilentChestStatus(Player player, boolean status) { - saveToConfig("toggles.silent-chest." + player.getUniqueId(), status); - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInv.java b/plugin/src/main/java/com/lishid/openinv/OpenInv.java index 4474e2b..7bc80e5 100644 --- a/plugin/src/main/java/com/lishid/openinv/OpenInv.java +++ b/plugin/src/main/java/com/lishid/openinv/OpenInv.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2016 lishid. All rights reserved. + * 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 @@ -17,57 +17,97 @@ package com.lishid.openinv; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; -import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; -import com.lishid.openinv.commands.AnyChestCommand; -import com.lishid.openinv.commands.OpenEnderCommand; -import com.lishid.openinv.commands.OpenInvCommand; -import com.lishid.openinv.commands.SearchEnderCommand; -import com.lishid.openinv.commands.SearchInvCommand; -import com.lishid.openinv.commands.SilentChestCommand; -import com.lishid.openinv.commands.ToggleOpenInvCommand; -import com.lishid.openinv.internal.IAnySilentChest; +import com.lishid.openinv.commands.AnyChestPluginCommand; +import com.lishid.openinv.commands.OpenEnderPluginCommand; +import com.lishid.openinv.commands.OpenInvPluginCommand; +import com.lishid.openinv.commands.SearchInvPluginCommand; +import com.lishid.openinv.commands.SilentChestPluginCommand; +import com.lishid.openinv.internal.IAnySilentContainer; import com.lishid.openinv.internal.IInventoryAccess; import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialEnderChest; import com.lishid.openinv.internal.ISpecialPlayerInventory; import com.lishid.openinv.internal.InternalAccessor; -import com.lishid.openinv.listeners.OpenInvEntityListener; -import com.lishid.openinv.listeners.OpenInvInventoryListener; -import com.lishid.openinv.listeners.OpenInvPlayerListener; +import com.lishid.openinv.util.Cache; +import com.lishid.openinv.util.Function; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.PluginCommand; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; -import org.bukkit.permissions.Permissible; +import org.bukkit.inventory.Inventory; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +/** + * Open other player's inventory + * + * @author lishid + */ public class OpenInv extends JavaPlugin { - private final Map inventories = new HashMap(); - private final Map enderChests = new HashMap(); + private final Map inventories = new HashMap(); + private final Map enderChests = new HashMap(); + private final Cache playerCache = new Cache(300000L, + new Function() { + @Override + public boolean run(Player value) { + String key = playerLoader.getPlayerDataID(value); + return inventories.containsKey(key) && inventories.get(key).isInUse() + || enderChests.containsKey(key) && enderChests.get(key).isInUse(); + } + }, + new Function() { + @Override + public boolean run(Player value) { + String key = playerLoader.getPlayerDataID(value); - private Configuration configuration; + // Check if inventory is stored, and if it is, remove it and eject all viewers + if (inventories.containsKey(key)) { + Inventory inv = inventories.remove(key).getBukkitInventory(); + for (HumanEntity entity : inv.getViewers()) { + entity.closeInventory(); + } + } + + // Check if ender chest is stored, and if it is, remove it and eject all viewers + if (enderChests.containsKey(key)) { + Inventory inv = enderChests.remove(key).getBukkitInventory(); + for (HumanEntity entity : inv.getViewers()) { + entity.closeInventory(); + } + } + + if (!OpenInv.this.disableSaving() && !value.isOnline()) { + value.saveData(); + } + return true; + } + }); private InternalAccessor accessor; private IPlayerDataManager playerLoader; private IInventoryAccess inventoryAccess; - private IAnySilentChest anySilentChest; + private IAnySilentContainer anySilentContainer; @Override public void onEnable() { - // Save the default config.yml if it doesn't already exist - saveDefaultConfig(); - - // Config - configuration = new Configuration(this); - + // Get plugin manager PluginManager pm = getServer().getPluginManager(); + accessor = new InternalAccessor(this); // Version check - if (!accessor.initialize(getServer())) { + if (!accessor.isSupported()) { getLogger().info("Your version of CraftBukkit (" + accessor.getVersion() + ") is not supported."); getLogger().info("Please look for an updated version of OpenInv."); pm.disablePlugin(this); @@ -76,195 +116,473 @@ public class OpenInv extends JavaPlugin { playerLoader = accessor.newPlayerDataManager(); inventoryAccess = accessor.newInventoryAccess(); - anySilentChest = accessor.newAnySilentChest(); + anySilentContainer = accessor.newAnySilentContainer(); + + FileConfiguration config = getConfig(); + boolean dirtyConfig = false; + if (!config.isBoolean("NotifySilentChest")) { + config.set("NotifySilentChest", true); + dirtyConfig = true; + } + if (!config.isBoolean("NotifyAnyChest")) { + config.set("NotifyAnyChest", true); + dirtyConfig = true; + } + if (!config.isBoolean("DisableSaving")) { + config.set("DisableSaving", false); + dirtyConfig = true; + } + config.addDefault("NotifySilentChest", true); + config.addDefault("NotifyAnyChest", true); + config.addDefault("DisableSaving", false); + config.options().copyDefaults(true); + if (dirtyConfig) { + saveConfig(); + } - // Register the plugin's events pm.registerEvents(new OpenInvPlayerListener(this), this); - pm.registerEvents(new OpenInvEntityListener(this), this); pm.registerEvents(new OpenInvInventoryListener(this), this); - // Register the plugin's commands - getCommand("openinv").setExecutor(new OpenInvCommand(this)); - getCommand("openender").setExecutor(new OpenEnderCommand(this)); - getCommand("searchinv").setExecutor(new SearchInvCommand(this)); - getCommand("searchender").setExecutor(new SearchEnderCommand()); - getCommand("toggleopeninv").setExecutor(new ToggleOpenInvCommand(this)); - getCommand("anychest").setExecutor(new AnyChestCommand(this)); - getCommand("silentchest").setExecutor(new SilentChestCommand(this)); + getCommand("openinv").setExecutor(new OpenInvPluginCommand(this)); + getCommand("searchinv").setExecutor(new SearchInvPluginCommand()); + getCommand("silentchest").setExecutor(new SilentChestPluginCommand(this)); + getCommand("anychest").setExecutor(new AnyChestPluginCommand(this)); + getCommand("openender").setExecutor(new OpenEnderPluginCommand(this)); + + } + + @Override + public void onDisable() { + + if (this.disableSaving()) { + return; + } + + this.playerCache.invalidateAll(); } /** - * Returns the plugin Configuration. - * - * @return the plugin Configuration + * Checks if the server version is supported by OpenInv. + * + * @return true if the server version is supported */ - public Configuration getConfiguration() { - return configuration; + public boolean isSupportedVersion() { + return accessor.isSupported(); } /** - * Returns an instance of PlayerDataManager. - * - * @return an instance of PlayerDataManager - */ - public IPlayerDataManager getPlayerLoader() { - return playerLoader; - } - - /** - * Returns an instance of InventoryAccess. - * - * @return an instance of InventoryAccess + * Gets the active IInventoryAccess implementation. May return null if the server version is + * unsupported. + * + * @return the IInventoryAccess */ public IInventoryAccess getInventoryAccess() { - return inventoryAccess; + return this.inventoryAccess; } /** - * Returns an instance of AnySilentChest. - * - * @return an instance of AnySilentChest + * Gets the active ISilentContainer implementation. May return null if the server version is + * unsupported. + * + * @return the ISilentContainer */ - public IAnySilentChest getAnySilentChest() { - return anySilentChest; + public IAnySilentContainer getAnySilentContainer() { + return this.anySilentContainer; } /** - * Returns a player's SpecialPlayerInventory. - * - * @param player the player to get the SpecialPlayerInventory of - * @param createIfNull whether or not to create it if it doesn't exist - * @return the player's SpecialPlayerInventory or null + * Gets an ISpecialPlayerInventory for the given Player. + * + * @param player the Player + * @param online true if the Player is currently online + * @return the ISpecialPlayerInventory */ - public ISpecialPlayerInventory getPlayerInventory(Player player, boolean createIfNull) { - ISpecialPlayerInventory inventory = inventories.get(player.getUniqueId()); + public ISpecialPlayerInventory getInventory(Player player, boolean online) { + String id = playerLoader.getPlayerDataID(player); + if (inventories.containsKey(id)) { + return inventories.get(id); + } + ISpecialPlayerInventory inv = accessor.newSpecialPlayerInventory(player, online); + inventories.put(id, inv); + playerCache.put(id, player); + return inv; + } - if (inventory == null && createIfNull) { - inventory = accessor.newSpecialPlayerInventory(player, !player.isOnline()); - inventories.put(player.getUniqueId(), inventory); + /** + * Gets an ISpecialEnderChest for the given Player. + * + * @param player the Player + * @param online true if the Player is currently online + * @return the ISpecialEnderChest + */ + public ISpecialEnderChest getEnderChest(Player player, boolean online) { + String id = playerLoader.getPlayerDataID(player); + if (enderChests.containsKey(id)) { + return enderChests.get(id); + } + ISpecialEnderChest inv = accessor.newSpecialEnderChest(player, online); + enderChests.put(id, inv); + playerCache.put(id, player); + return inv; + } + + /** + * Forcibly unload a cached Player's data. + * + * @param player the OfflinePlayer to unload + */ + public void unload(OfflinePlayer player) { + this.playerCache.invalidate(this.playerLoader.getPlayerDataID(player)); + } + + /** + * Check the configuration value for whether or not OpenInv saves player data when unloading + * players. This is exclusively for users who do not allow editing of inventories, only viewing, + * and wish to prevent any possibility of bugs such as lishid#40. If true, OpenInv will not ever + * save any edits made to players. + * + * @return false unless configured otherwise + */ + public boolean disableSaving() { + return getConfig().getBoolean("DisableSaving", false); + } + + /** + * Check the configuration value for whether or not OpenInv displays a notification to the user + * when a container is activated with SilentChest. + * + * @return true unless configured otherwise + */ + public boolean notifySilentChest() { + return getConfig().getBoolean("NotifySilentChest", true); + } + + /** + * Check the configuration value for whether or not OpenInv displays a notification to the user + * when a container is activated with AnyChest. + * + * @return true unless configured otherwise + */ + public boolean notifyAnyChest() { + return getConfig().getBoolean("NotifyAnyChest", true); + } + + /** + * Gets a player's SilentChest setting. + * + * @param player the OfflinePlayer + * @return true if SilentChest is enabled + */ + public boolean getPlayerSilentChestStatus(OfflinePlayer player) { + return getConfig().getBoolean("SilentChest." + playerLoader.getPlayerDataID(player) + ".toggle", false); + } + + /** + * Sets a player's SilentChest setting. + * + * @param player the OfflinePlayer + * @param status the status + */ + public void setPlayerSilentChestStatus(OfflinePlayer player, boolean status) { + getConfig().set("SilentChest." + playerLoader.getPlayerDataID(player) + ".toggle", status); + saveConfig(); + } + + /** + * Gets the provided player's AnyChest setting. + * + * @param player the OfflinePlayer + * @return true if AnyChest is enabled + */ + public boolean getPlayerAnyChestStatus(OfflinePlayer player) { + return getConfig().getBoolean("AnyChest." + playerLoader.getPlayerDataID(player) + ".toggle", true); + } + + /** + * Sets a player's AnyChest setting. + * + * @param player the OfflinePlayer + * @param status the status + */ + public void setPlayerAnyChestStatus(OfflinePlayer player, boolean status) { + getConfig().set("AnyChest." + playerLoader.getPlayerDataID(player) + ".toggle", status); + saveConfig(); + } + + /** + * Get an OfflinePlayer by name. + *

+ * Note: This method is potentially very heavily blocking. It should not ever be called on the + * main thread, and if it is, a stack trace will be displayed alerting server owners to the + * call. + * + * @param name the name of the Player + * @return the OfflinePlayer with the closest matching name or null if no players have ever logged in + */ + public OfflinePlayer matchPlayer(String name) { + + // Warn if called on the main thread - if we resort to searching offline players, this may take several seconds. + if (getServer().isPrimaryThread()) { + getLogger().warning("Call to OpenInv#matchPlayer made on the main thread!"); + getLogger().warning("This can cause the server to hang, potentially severely."); + getLogger().warning("Trace:"); + for (StackTraceElement element : new Throwable().fillInStackTrace().getStackTrace()) { + getLogger().warning(element.toString()); + } } - return inventory; - } - - /** - * Returns a player's SpecialEnderChest. - * - * @param player the player to get the SpecialEnderChest of - * @param createIfNull whether or not to create it if it doesn't exist - * @return the player's SpecialEnderChest or null - */ - public ISpecialEnderChest getPlayerEnderChest(Player player, boolean createIfNull) { - ISpecialEnderChest enderChest = enderChests.get(player.getUniqueId()); - - if (enderChest == null && createIfNull) { - enderChest = accessor.newSpecialEnderChest(player, player.isOnline()); - enderChests.put(player.getUniqueId(), enderChest); + // Ensure name is valid if server is in online mode to avoid unnecessary searching + if (getServer().getOnlineMode() && !name.matches("[a-zA-Z0-9_]{3,16}")) { + return null; } - return enderChest; - } + OfflinePlayer player = getServer().getPlayerExact(name); - /** - * Removes a player's loaded inventory if it exists. - * - * @param player the player to remove the loaded inventory of - */ - public void removeLoadedInventory(Player player) { - if (inventories.containsKey(player.getUniqueId())) { - inventories.remove(player.getUniqueId()); + if (player != null) { + return player; } - } - /** - * Removes a player's loaded ender chest if it exists. - * - * @param player the player to remove the loaded ender chest of - */ - public void removeLoadedEnderChest(Player player) { - if (enderChests.containsKey(player.getUniqueId())) { - enderChests.remove(player.getUniqueId()); + player = getServer().getOfflinePlayer(name); + + /* + * Compatibility: Pre-UUID, getOfflinePlayer always returns an OfflinePlayer. Post-UUID, + * getOfflinePlayer will return null if no matching player is found. To preserve + * compatibility, only return the player if they have played before. Ignoring current online + * status is fine, they'd have been found by getPlayerExact otherwise. + */ + if (player != null && player.hasPlayedBefore()) { + return player; } - } - /** - * Logs a message to console. - * - * @param text the message to log - */ - public void log(String text) { - getLogger().info(text); - } + player = getServer().getPlayer(name); - /** - * Logs a Throwable to console. - * - * @param e the Throwable to log - */ - public void log(Throwable e) { - getLogger().severe(e.toString()); - e.printStackTrace(); - } + if (player != null) { + return player; + } - /** - * Sends an OpenInv message to a player. - * - * @param sender the CommandSender to message - * @param message the message to send - */ - public static void sendMessage(CommandSender sender, String message) { - sender.sendMessage(ChatColor.AQUA + "[OpenInv] " + ChatColor.WHITE + message); - } - - /** - * Outputs OpenInv help information to a CommandSender. - * - * @param sender the CommandSender to show help to - */ - public static void showHelp(CommandSender sender) { - sender.sendMessage(ChatColor.GREEN + "/openinv - Opens a player's inventory."); - sender.sendMessage(ChatColor.GREEN + " (aliases: oi, inv, open)"); - - sender.sendMessage(ChatColor.GREEN + "/openender - Opens a player's ender chest."); - sender.sendMessage(ChatColor.GREEN + " (aliases: oe)"); - - sender.sendMessage(ChatColor.GREEN + "/searchinv [minAmount] -"); - sender.sendMessage(ChatColor.GREEN + " Searches and lists players that have a specific item in their inventory."); - sender.sendMessage(ChatColor.GREEN + " (aliases: si)"); - - sender.sendMessage(ChatColor.GREEN + "/searchender [minAmount] -"); - sender.sendMessage(ChatColor.GREEN + " Searches and lists players that have a specific item in their ender chest."); - sender.sendMessage(ChatColor.GREEN + " (aliases: se)"); - - sender.sendMessage(ChatColor.GREEN + "/toggleopeninv - Toggles the item openinv function."); - sender.sendMessage(ChatColor.GREEN + " (aliases: toi, toggleoi, toggleinv)"); - - sender.sendMessage(ChatColor.GREEN + "/anychest - Toggles the any chest function."); - sender.sendMessage(ChatColor.GREEN + " (aliases: ac)"); - - sender.sendMessage(ChatColor.GREEN + "/silentchest - Toggles the silent chest function."); - sender.sendMessage(ChatColor.GREEN + " (aliases: sc, silent)"); - } - - /** - * Returns whether or not a player has a permission. - * - * @param player the player to check - * @param permission the permission node to check for - * @return true if the player has the permission; false otherwise - */ - public static boolean hasPermission(Permissible player, String permission) { - String[] parts = permission.split("\\."); - String perm = ""; - - for (int i = 0; i < parts.length; i++) { - if (player.hasPermission(perm + "*")) { - return true; + int bestMatch = Integer.MAX_VALUE; + for (OfflinePlayer offline : getServer().getOfflinePlayers()) { + if (offline.getName() == null) { + // Loaded by UUID only, name has never been looked up. + continue; } - perm += parts[i] + "."; + // Compatibility: Lang3 is only bundled with 1.8+ + int currentMatch = org.apache.commons.lang.StringUtils.getLevenshteinDistance(name, offline.getName()); + + if (currentMatch == 0) { + return offline; + } + + if (currentMatch < bestMatch) { + bestMatch = currentMatch; + player = offline; + } } - return player.hasPermission(permission); + // Only null if no players have played ever, otherwise even the worst match will do. + return player; } + + /** + * Load a Player from an OfflinePlayer. May return null under some circumstances. + * + * @param offline the OfflinePlayer to load a Player for + * @return the Player + */ + public Player loadPlayer(final OfflinePlayer offline) { + + if (offline == null) { + return null; + } + + String key = this.playerLoader.getPlayerDataID(offline); + if (this.playerCache.containsKey(key)) { + return this.playerCache.get(key); + } + + Player loaded; + + if (offline.isOnline()) { + loaded = offline.getPlayer(); + this.playerCache.put(key, loaded); + return loaded; + } + + if (Bukkit.isPrimaryThread()) { + return this.playerLoader.loadPlayer(offline); + } + + Future future = Bukkit.getScheduler().callSyncMethod(this, + new Callable() { + @Override + public Player call() throws Exception { + return playerLoader.loadPlayer(offline); + } + }); + + int ticks = 0; + while (!future.isDone() && !future.isCancelled() && ticks < 10) { + ++ticks; + try { + Thread.sleep(50L); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } + } + + if (!future.isDone() || future.isCancelled()) { + return null; + } + + try { + loaded = future.get(); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } catch (ExecutionException e) { + e.printStackTrace(); + return null; + } + + if (loaded != null) { + this.playerCache.put(key, loaded); + } + + return loaded; + } + + /** + * Method for handling a Player coming online. + * + * @param player the Player + */ + public void setPlayerOnline(final Player player) { + + String key = this.playerLoader.getPlayerDataID(player); + + // Check if the player is cached. If not, neither of their inventories is open. + if (!this.playerCache.containsKey(key)) { + return; + } + + this.playerCache.put(key, player); + + if (this.inventories.containsKey(key)) { + this.inventories.get(key).setPlayerOnline(player); + new BukkitRunnable() { + @Override + public void run() { + if (player.isOnline()) { + player.updateInventory(); + } + } + }.runTask(this); + } + + if (this.enderChests.containsKey(key)) { + this.enderChests.get(key).setPlayerOnline(player); + } + } + + /** + * Method for handling a Player going offline. + * + * @param player the Player + */ + public void setPlayerOffline(final Player player) { + + String key = this.playerLoader.getPlayerDataID(player); + + // Check if the player is cached. If not, neither of their inventories is open. + if (!this.playerCache.containsKey(key)) { + return; + } + + if (this.inventories.containsKey(key)) { + this.inventories.get(key).setPlayerOffline(); + } + + if (this.enderChests.containsKey(key)) { + this.enderChests.get(key).setPlayerOffline(); + } + } + + /** + * Evicts all viewers lacking cross-world permissions from a Player's inventory. + * + * @param player the Player + */ + public void changeWorld(final Player player) { + + String key = this.playerLoader.getPlayerDataID(player); + + // Check if the player is cached. If not, neither of their inventories is open. + if (!this.playerCache.containsKey(key)) { + return; + } + + if (this.inventories.containsKey(key)) { + Iterator iterator = this.inventories.get(key).getBukkitInventory().getViewers().iterator(); + while (iterator.hasNext()) { + HumanEntity human = iterator.next(); + // If player has permission or is in the same world, allow continued access + // Just in case, also allow null worlds. + if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld() == null + || human.getWorld().equals(player.getWorld())) { + continue; + } + human.closeInventory(); + } + } + + if (this.enderChests.containsKey(key)) { + Iterator iterator = this.enderChests.get(key).getBukkitInventory().getViewers().iterator(); + while (iterator.hasNext()) { + HumanEntity human = iterator.next(); + if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld() == null + || human.getWorld().equals(player.getWorld())) { + continue; + } + human.closeInventory(); + } + } + } + + /** + * Displays all applicable help for OpenInv commands. + * + * @param player the Player to help + */ + public void showHelp(Player player) { + // Get registered commands + for (String commandName : this.getDescription().getCommands().keySet()) { + PluginCommand command = this.getCommand(commandName); + + // Ensure command is successfully registered and player can use it + if (command == null || !command.testPermissionSilent(player)) { + continue; + } + + // Send usage + player.sendMessage(command.getUsage()); + + List aliases = command.getAliases(); + if (aliases.isEmpty()) { + continue; + } + + // Assemble alias list + StringBuilder aliasBuilder = new StringBuilder(" (aliases: "); + for (String alias : aliases) { + aliasBuilder.append(alias).append(", "); + } + aliasBuilder.delete(aliasBuilder.length() - 2, aliasBuilder.length()).append(')'); + + // Send all aliases + player.sendMessage(aliasBuilder.toString()); + } + } + } diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInvInventoryListener.java b/plugin/src/main/java/com/lishid/openinv/OpenInvInventoryListener.java new file mode 100644 index 0000000..f9eba2c --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/OpenInvInventoryListener.java @@ -0,0 +1,62 @@ +/* + * 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; + +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.inventory.Inventory; + +public class OpenInvInventoryListener implements Listener { + + private final OpenInv plugin; + + public OpenInvInventoryListener(OpenInv plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent event) { + if (cancelInteract(event.getWhoClicked(), event.getInventory())) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onInventoryDrag(InventoryDragEvent event) { + if (cancelInteract(event.getWhoClicked(), event.getInventory())) { + event.setCancelled(true); + } + } + + private boolean cancelInteract(HumanEntity entity, Inventory inventory) { + return plugin.getInventoryAccess().isSpecialPlayerInventory(inventory) + && !Permissions.EDITINV.hasPermission(entity) + || plugin.getInventoryAccess().isSpecialEnderChest(inventory) + && !Permissions.EDITENDER.hasPermission(entity); + } + + @EventHandler + public void onWorldChange(PlayerChangedWorldEvent event) { + plugin.changeWorld(event.getPlayer()); + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInvPlayerListener.java b/plugin/src/main/java/com/lishid/openinv/OpenInvPlayerListener.java new file mode 100644 index 0000000..d0c65ff --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/OpenInvPlayerListener.java @@ -0,0 +1,78 @@ +/* + * 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; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event.Result; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class OpenInvPlayerListener implements Listener { + + private final OpenInv plugin; + + public OpenInvPlayerListener(OpenInv plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(final PlayerJoinEvent event) { + plugin.setPlayerOnline(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) { + plugin.setPlayerOffline(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK || event.getPlayer().isSneaking() + || event.useInteractedBlock() == Result.DENY + || !plugin.getAnySilentContainer().isAnySilentContainer(event.getClickedBlock())) { + return; + } + + Player player = event.getPlayer(); + boolean anychest = Permissions.ANYCHEST.hasPermission(player) && plugin.getPlayerAnyChestStatus(player); + boolean needsAnyChest = plugin.getAnySilentContainer().isAnyContainerNeeded(player, event.getClickedBlock()); + + if (!anychest && needsAnyChest) { + return; + } + + boolean silentchest = Permissions.SILENT.hasPermission(player) && plugin.getPlayerSilentChestStatus(player); + + // If anychest or silentchest is active + if ((anychest || silentchest) && plugin.getAnySilentContainer().activateContainer(player, silentchest, event.getClickedBlock())) { + if (silentchest && plugin.notifySilentChest() && needsAnyChest && plugin.notifyAnyChest()) { + player.sendMessage("You are opening a blocked container silently."); + } else if (silentchest && plugin.notifySilentChest()) { + player.sendMessage("You are opening a container silently."); + } else if (needsAnyChest && plugin.notifyAnyChest()) { + player.sendMessage("You are opening a blocked container."); + } + event.setCancelled(true); + } + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/Permissions.java b/plugin/src/main/java/com/lishid/openinv/Permissions.java index 0577a51..b08fc6a 100644 --- a/plugin/src/main/java/com/lishid/openinv/Permissions.java +++ b/plugin/src/main/java/com/lishid/openinv/Permissions.java @@ -1,19 +1,38 @@ package com.lishid.openinv; -public final class Permissions { +import org.bukkit.permissions.Permissible; - private Permissions() {} +public enum Permissions { + + OPENINV("OpenInv.openinv"), + OVERRIDE("OpenInv.override"), + EXEMPT("OpenInv.exempt"), + CROSSWORLD("OpenInv.crossworld"), + SILENT("OpenInv.silent"), + ANYCHEST("OpenInv.anychest"), + ENDERCHEST("OpenInv.openender"), + ENDERCHEST_ALL("OpenInv.openenderall"), + SEARCH("OpenInv.search"), + EDITINV("OpenInv.editinv"), + EDITENDER("OpenInv.editender"), + OPENSELF("OpenInv.openself"); + + private final String permission; + + private Permissions(String permission) { + this.permission = permission; + } + + public boolean hasPermission(Permissible permissible) { + String[] parts = permission.split("\\."); + String perm = ""; + for (int i = 0; i < parts.length; i++) { + if (permissible.hasPermission(perm + "*")) { + return true; + } + perm += parts[i] + "."; + } + return permissible.hasPermission(permission); + } - public static final String PERM_OPENINV = "OpenInv.openinv"; - public static final String PERM_OVERRIDE = "OpenInv.override"; - public static final String PERM_EXEMPT = "OpenInv.exempt"; - public static final String PERM_CROSSWORLD = "OpenInv.crossworld"; - public static final String PERM_SILENT = "OpenInv.silent"; - public static final String PERM_ANYCHEST = "OpenInv.anychest"; - public static final String PERM_ENDERCHEST = "OpenInv.openender"; - public static final String PERM_ENDERCHEST_ALL = "OpenInv.openenderall"; - public static final String PERM_SEARCH = "OpenInv.search"; - public static final String PERM_EDITINV = "OpenInv.editinv"; - public static final String PERM_EDITENDER = "OpenInv.editender"; - public static final String PERM_OPENSELF = "OpenInv.openself"; } diff --git a/plugin/src/main/java/com/lishid/openinv/commands/AnyChestCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/AnyChestCommand.java deleted file mode 100644 index 1cfdd85..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/AnyChestCommand.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.Configuration; - -public class AnyChestCommand implements CommandExecutor { - - private final OpenInv plugin; - private final Configuration configuration; - - public AnyChestCommand(OpenInv plugin) { - this.plugin = plugin; - configuration = plugin.getConfiguration(); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("anychest")) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "You can't use this command from the console."); - return true; - } - - if (!OpenInv.hasPermission(sender, Permissions.PERM_ANYCHEST)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to use any chest."); - return true; - } - - Player player = (Player) sender; - - if (args.length > 0) { - if (args[0].equalsIgnoreCase("check")) { - String status = configuration.getPlayerAnyChestStatus(player) ? ChatColor.GREEN + "ON" : ChatColor.RED + "OFF"; - OpenInv.sendMessage(player, "Any Chest is " + status + ChatColor.RESET + "."); - return true; - } - } - - configuration.setPlayerAnyChestStatus(player, !configuration.getPlayerAnyChestStatus(player)); - - String status = configuration.getPlayerAnyChestStatus(player) ? ChatColor.GREEN + "ON" : ChatColor.RED + "OFF"; - OpenInv.sendMessage(player, "Any Chest is now " + status + ChatColor.RESET + "."); - - return true; - } - - return false; - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/AnyChestPluginCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/AnyChestPluginCommand.java new file mode 100644 index 0000000..3036f30 --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/commands/AnyChestPluginCommand.java @@ -0,0 +1,54 @@ +/* + * 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.commands; + +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.lishid.openinv.OpenInv; + +public class AnyChestPluginCommand implements CommandExecutor { + + private final OpenInv plugin; + + public AnyChestPluginCommand(OpenInv plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "You can't use this from the console."); + return true; + } + + Player player = (Player) sender; + + if (args.length > 0 && args[0].equalsIgnoreCase("check")) { + sender.sendMessage("AnyChest is " + (plugin.getPlayerAnyChestStatus(player) ? "ON" : "OFF") + "."); + return true; + } + + plugin.setPlayerAnyChestStatus(player, !plugin.getPlayerAnyChestStatus(player)); + sender.sendMessage("AnyChest is now " + (plugin.getPlayerAnyChestStatus(player) ? "ON" : "OFF") + "."); + + return true; + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/OpenEnderCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/OpenEnderCommand.java deleted file mode 100644 index aef46ca..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/OpenEnderCommand.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.commands; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.internal.ISpecialEnderChest; -import com.lishid.openinv.utils.UUIDUtils; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class OpenEnderCommand implements CommandExecutor { - - private final OpenInv plugin; - private final Map openEnderHistory = new ConcurrentHashMap(); - - public OpenEnderCommand(OpenInv plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("openender")) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "You can't use this command from the console."); - return true; - } - - if (!OpenInv.hasPermission(sender, Permissions.PERM_ENDERCHEST)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to access player ender chests."); - return true; - } - - if (args.length > 0 && args[0].equalsIgnoreCase("?")) { - OpenInv.showHelp(sender); - return true; - } - - final Player player = (Player) sender; - - // History management - UUID history = openEnderHistory.get(player.getUniqueId()); - if (history == null) { - history = player.getUniqueId(); - openEnderHistory.put(player.getUniqueId(), history); - } - - final UUID uuid; - - // Read from history if target is not named - if (args.length < 1) { - if (history != null) { - uuid = history; - } else { - sender.sendMessage(ChatColor.RED + "OpenEnder history is empty!"); - return true; - } - } - else { - uuid = UUIDUtils.getPlayerUUID(args[0]); - if (uuid == null) { - player.sendMessage(ChatColor.RED + "Player not found!"); - return true; - } - } - - final UUID playerUUID = player.getUniqueId(); - - Player target = Bukkit.getPlayer(uuid); - if (target == null) { - // Targeted player was not found online, start asynchronous lookup in files - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - // Try loading the player's data asynchronously - final Player target = plugin.getPlayerLoader().loadPlayer(uuid); - if (target == null) { - player.sendMessage(ChatColor.RED + "Player not found!"); - return; - } - - // Open target's inventory synchronously - Bukkit.getScheduler().runTask(plugin, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(playerUUID); - // If sender is no longer online after loading the target, abort! - if (player == null) { - return; - } - - openInventory(player, target); - } - }); - } - }); - } else { - openInventory(player, target); - } - - return true; - } - - return false; - } - - private void openInventory(Player player, Player target) { - // Null target check - if (target == null) { - player.sendMessage(ChatColor.RED + "Player not found!"); - return; - } - - // Permissions checks - if (target != player && !OpenInv.hasPermission(player, Permissions.PERM_ENDERCHEST_ALL)) { - player.sendMessage(ChatColor.RED + "You do not have permission to access other player's ender chests."); - return; - } - - if (!OpenInv.hasPermission(player, Permissions.PERM_OVERRIDE) && OpenInv.hasPermission(target, Permissions.PERM_EXEMPT)) { - player.sendMessage(ChatColor.RED + target.getDisplayName() + "'s ender chest is protected!"); - return; - } - - // Crossworld check - if ((!OpenInv.hasPermission(player, Permissions.PERM_CROSSWORLD) && !OpenInv.hasPermission(player, Permissions.PERM_OVERRIDE)) && target.getWorld() != player.getWorld()) { - player.sendMessage(ChatColor.RED + target.getDisplayName() + " is not in your world!"); - return; - } - - // Record the target - openEnderHistory.put(player.getUniqueId(), target.getUniqueId()); - - // Get the inventory and open it - ISpecialEnderChest enderChest = plugin.getPlayerEnderChest(target, true); - player.openInventory(enderChest.getBukkitInventory()); - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java new file mode 100644 index 0000000..96995e6 --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/commands/OpenEnderPluginCommand.java @@ -0,0 +1,132 @@ +/* + * 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.commands; + +import java.util.HashMap; + +import com.lishid.openinv.OpenInv; +import com.lishid.openinv.Permissions; +import com.lishid.openinv.internal.ISpecialEnderChest; + +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public class OpenEnderPluginCommand implements CommandExecutor { + + private final OpenInv plugin; + private final HashMap openEnderHistory = new HashMap(); + + public OpenEnderPluginCommand(OpenInv plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "You can't use this from the console."); + return true; + } + + if (args.length > 0 && args[0].equalsIgnoreCase("?")) { + plugin.showHelp((Player) sender); + return true; + } + + final Player player = (Player) sender; + + // History management + String history = openEnderHistory.get(player); + + if (history == null || history == "") { + history = player.getName(); + openEnderHistory.put(player, history); + } + + final String name; + + // Read from history if target is not named + if (args.length < 1) { + name = history; + } else { + name = args[0]; + } + + new BukkitRunnable() { + @Override + public void run() { + final OfflinePlayer offlinePlayer = plugin.matchPlayer(name); + + if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) { + player.sendMessage(ChatColor.RED + "Player not found!"); + return; + } + + new BukkitRunnable() { + @Override + public void run() { + if (!player.isOnline()) { + return; + } + openInventory(player, offlinePlayer); + } + }.runTask(plugin); + + } + }.runTaskAsynchronously(plugin); + + return true; + } + + private void openInventory(Player player, OfflinePlayer target) { + + Player onlineTarget; + boolean online = target.isOnline(); + + if (!online) { + // Try loading the player's data + onlineTarget = plugin.loadPlayer(target); + + if (onlineTarget == null) { + player.sendMessage(ChatColor.RED + "Player not found!"); + return; + } + } else { + onlineTarget = target.getPlayer(); + } + + + if (!onlineTarget.equals(player) && !Permissions.ENDERCHEST_ALL.hasPermission(player)) { + player.sendMessage(ChatColor.RED + "You do not have permission to access other player's enderchest"); + return; + } + + // Record the target + openEnderHistory.put(player, onlineTarget.getName()); + + // Create the inventory + ISpecialEnderChest chest = plugin.getEnderChest(onlineTarget, online); + + // Open the inventory + player.openInventory(chest.getBukkitInventory()); + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/OpenInvCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/OpenInvCommand.java deleted file mode 100644 index 0b2e37a..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/OpenInvCommand.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.commands; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.internal.ISpecialPlayerInventory; -import com.lishid.openinv.utils.UUIDUtils; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class OpenInvCommand implements CommandExecutor { - - private final OpenInv plugin; - private final Map openInvHistory = new ConcurrentHashMap(); - - public OpenInvCommand(OpenInv plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("openinv")) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "You can't use this command from the console."); - return true; - } - - if (!OpenInv.hasPermission(sender, Permissions.PERM_OPENINV)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to access player inventories."); - return true; - } - - if (args.length > 0 && args[0].equalsIgnoreCase("?")) { - OpenInv.showHelp(sender); - return true; - } - - final Player player = (Player) sender; - - // History management - UUID history = openInvHistory.get(player.getUniqueId()); - if (history == null) { - history = player.getUniqueId(); - openInvHistory.put(player.getUniqueId(), history); - } - - final UUID uuid; - - // Read from history if target is not named - if (args.length < 1) { - uuid = history; - } else { - uuid = UUIDUtils.getPlayerUUID(args[0]); - if (uuid == null) { - player.sendMessage(ChatColor.RED + "Player not found!"); - return true; - } - } - - final UUID playerUUID = player.getUniqueId(); - - Player target = Bukkit.getPlayer(uuid); - if (target == null) { - // Targeted player was not found online, start asynchronous lookup in files - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - // Try loading the player's data asynchronously - final Player target = plugin.getPlayerLoader().loadPlayer(uuid); - if (target == null) { - player.sendMessage(ChatColor.RED + "Player not found!"); - return; - } - - // Open target's inventory synchronously - Bukkit.getScheduler().runTask(plugin, new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(playerUUID); - // If sender is no longer online after loading the target, abort! - if (player == null) { - return; - } - - openInventory(player, target); - } - }); - } - }); - } else { - openInventory(player, target); - } - - return true; - } - - return false; - } - - private void openInventory(Player player, Player target) { - // Null target check - if (target == null) { - player.sendMessage(ChatColor.RED + "Player not found!"); - return; - } - - // Permissions checks - if (!OpenInv.hasPermission(player, Permissions.PERM_OVERRIDE) && OpenInv.hasPermission(target, Permissions.PERM_EXEMPT)) { - player.sendMessage(ChatColor.RED + target.getDisplayName() + "'s inventory is protected!"); - return; - } - - // Crossworld check - if ((!OpenInv.hasPermission(player, Permissions.PERM_CROSSWORLD) && !OpenInv.hasPermission(player, Permissions.PERM_OVERRIDE)) && target.getWorld() != player.getWorld()) { - player.sendMessage(ChatColor.RED + target.getDisplayName() + " is not in your world!"); - return; - } - - // Self-open check - if (!OpenInv.hasPermission(player, Permissions.PERM_OPENSELF) && target.equals(player)) { - player.sendMessage(ChatColor.RED + "You're not allowed to openinv yourself."); - return; - } - - // Record the target - openInvHistory.put(player.getUniqueId(), target.getUniqueId()); - - // Get the inventory and open it - ISpecialPlayerInventory inventory = plugin.getPlayerInventory(target, true); - player.openInventory(inventory.getBukkitInventory()); - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java new file mode 100644 index 0000000..4ac56f8 --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/commands/OpenInvPluginCommand.java @@ -0,0 +1,145 @@ +/* + * 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.commands; + +import java.util.HashMap; + +import com.lishid.openinv.OpenInv; +import com.lishid.openinv.Permissions; +import com.lishid.openinv.internal.ISpecialPlayerInventory; + +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public class OpenInvPluginCommand implements CommandExecutor { + + private final OpenInv plugin; + private final HashMap openInvHistory = new HashMap(); + + public OpenInvPluginCommand(OpenInv plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "You can't use this from the console."); + return true; + } + + if (args.length > 0 && args[0].equalsIgnoreCase("?")) { + plugin.showHelp((Player) sender); + return true; + } + + final Player player = (Player) sender; + + // History management + String history = openInvHistory.get(player); + + if (history == null || history == "") { + history = player.getName(); + openInvHistory.put(player, history); + } + + final String name; + + // Read from history if target is not named + if (args.length < 1) { + name = history; + } else { + name = args[0]; + } + + new BukkitRunnable() { + @Override + public void run() { + final OfflinePlayer offlinePlayer = plugin.matchPlayer(name); + + if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) { + player.sendMessage(ChatColor.RED + "Player not found!"); + return; + } + + new BukkitRunnable() { + @Override + public void run() { + if (!player.isOnline()) { + return; + } + openInventory(player, offlinePlayer); + } + }.runTask(plugin); + + } + }.runTaskAsynchronously(plugin); + + return true; + } + + private void openInventory(Player player, OfflinePlayer target) { + + + Player onlineTarget; + boolean online = target.isOnline(); + + if (!online) { + // Try loading the player's data + onlineTarget = plugin.loadPlayer(target); + + if (onlineTarget == null) { + player.sendMessage(ChatColor.RED + "Player not found!"); + return; + } + } else { + onlineTarget = target.getPlayer(); + } + + // Permissions checks + if (!Permissions.OVERRIDE.hasPermission(player) && Permissions.EXEMPT.hasPermission(onlineTarget)) { + player.sendMessage(ChatColor.RED + onlineTarget.getDisplayName() + "'s inventory is protected!"); + return; + } + + // Crosswork check + if ((!Permissions.CROSSWORLD.hasPermission(player) && !Permissions.OVERRIDE.hasPermission(player)) && onlineTarget.getWorld() != player.getWorld()) { + player.sendMessage(ChatColor.RED + onlineTarget.getDisplayName() + " is not in your world!"); + return; + } + + // Self-open check + if (!Permissions.OPENSELF.hasPermission(player) && onlineTarget.equals(player)) { + player.sendMessage(ChatColor.RED + "You're not allowed to openinv yourself."); + return; + } + + // Record the target + openInvHistory.put(player, onlineTarget.getName()); + + // Create the inventory + ISpecialPlayerInventory inv = plugin.getInventory(onlineTarget, online); + + // Open the inventory + player.openInventory(inv.getBukkitInventory()); + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/SearchEnderCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/SearchEnderCommand.java deleted file mode 100644 index aa30025..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/SearchEnderCommand.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.lishid.openinv.commands; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; - -public class SearchEnderCommand implements CommandExecutor { - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("searchender")) { - if (sender instanceof Player) { - if (!OpenInv.hasPermission(sender, Permissions.PERM_SEARCH)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to search player ender chests."); - return true; - } - } - - Material material = null; - int count = 1; - - if (args.length >= 1) { - String[] gData; - gData = args[0].split(":"); - material = Material.matchMaterial(gData[0]); - } - - if (args.length >= 2) { - try { - count = Integer.parseInt(args[1]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "'" + args[1] + "' is not a number!"); - return false; - } - } - - if (material == null) { - sender.sendMessage(ChatColor.RED + "Unknown item."); - return false; - } - - StringBuilder sb = new StringBuilder(); - - for (Player onlinePlayer : Bukkit.getServer().getOnlinePlayers()) { - if (onlinePlayer.getEnderChest().contains(material, count)) { - sb.append(onlinePlayer.getName()); - sb.append(" "); - } - } - - String playerList = sb.toString(); - sender.sendMessage("Players with the item " + ChatColor.GRAY + material.toString() + ChatColor.RESET + " in their ender chest: " + playerList); - - return true; - } - - return false; - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/SearchInvCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/SearchInvCommand.java deleted file mode 100644 index 481b635..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/SearchInvCommand.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.commands; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; - -public class SearchInvCommand implements CommandExecutor { - - private final OpenInv plugin; - - public SearchInvCommand(OpenInv plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("searchinv")) { - if (sender instanceof Player) { - if (!OpenInv.hasPermission(sender, Permissions.PERM_SEARCH)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to search player inventories."); - return true; - } - } - - Material material = null; - int count = 1; - - if (args.length >= 1) { - String[] gData; - gData = args[0].split(":"); - material = Material.matchMaterial(gData[0]); - } - - if (args.length >= 2) { - try { - count = Integer.parseInt(args[1]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "'" + args[1] + "' is not a number!"); - return false; - } - } - - if (material == null) { - sender.sendMessage(ChatColor.RED + "Unknown item."); - return false; - } - - StringBuilder sb = new StringBuilder(); - - for (Player onlinePlayer : Bukkit.getServer().getOnlinePlayers()) { - if (onlinePlayer.getInventory().contains(material, count)) { - sb.append(onlinePlayer.getName()); - sb.append(" "); - } - } - - String playerList = sb.toString(); - sender.sendMessage("Players with the item " + ChatColor.GRAY + material.toString() + ChatColor.RESET + " in their inventory: " + playerList); - - return true; - } - - return false; - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/SearchInvPluginCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/SearchInvPluginCommand.java new file mode 100644 index 0000000..917d883 --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/commands/SearchInvPluginCommand.java @@ -0,0 +1,72 @@ +/* + * 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.commands; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SearchInvPluginCommand implements CommandExecutor { + + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + + Material material = null; + int count = 1; + + if (args.length >= 1) { + String[] gData = null; + gData = args[0].split(":"); + material = Material.matchMaterial(gData[0]); + } + + if (args.length >= 2) { + try { + count = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + sender.sendMessage(ChatColor.RED + "'" + args[1] + "' is not a number!"); + return false; + } + } + + if (material == null) { + sender.sendMessage(ChatColor.RED + "Unknown item"); + return false; + } + + StringBuilder players = new StringBuilder(); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + if (player.getInventory().contains(material, count)) { + players.append(player.getName()).append(", "); + } + } + + // Matches found, delete trailing comma and space + if (players.length() > 0) { + players.delete(players.length() - 2, players.length()); + } else { + sender.sendMessage("No players found with " + material.toString()); + } + + sender.sendMessage("Players with the item " + material.toString() + ": " + players.toString()); + return true; + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/SilentChestCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/SilentChestCommand.java deleted file mode 100644 index 6b14379..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/SilentChestCommand.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.Configuration; - -public class SilentChestCommand implements CommandExecutor { - - private final OpenInv plugin; - private final Configuration configuration; - - public SilentChestCommand(OpenInv plugin) { - this.plugin = plugin; - configuration = plugin.getConfiguration(); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("silentchest")) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "You can't use this command from the console."); - return true; - } - - if (!OpenInv.hasPermission(sender, Permissions.PERM_SILENT)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to use silent chest."); - return true; - } - - Player player = (Player) sender; - - if (args.length > 0) { - if (args[0].equalsIgnoreCase("check")) { - String status = configuration.getPlayerSilentChestStatus(player) ? ChatColor.GREEN + "ON" : ChatColor.RED + "OFF"; - OpenInv.sendMessage(player, "Silent Chest is " + status + ChatColor.RESET + "."); - return true; - } - } - - configuration.setPlayerSilentChestStatus(player, !configuration.getPlayerSilentChestStatus(player)); - - String status = configuration.getPlayerSilentChestStatus(player) ? ChatColor.GREEN + "ON" : ChatColor.RED + "OFF"; - OpenInv.sendMessage(player, "Silent Chest is now " + status + ChatColor.RESET + "."); - - return true; - } - - return false; - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/SilentChestPluginCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/SilentChestPluginCommand.java new file mode 100644 index 0000000..3710f6e --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/commands/SilentChestPluginCommand.java @@ -0,0 +1,53 @@ +/* + * 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.commands; + +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.lishid.openinv.OpenInv; + +public class SilentChestPluginCommand implements CommandExecutor { + + private final OpenInv plugin; + + public SilentChestPluginCommand(OpenInv plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "You can't use this from the console."); + return true; + } + + Player player = (Player) sender; + + if (args.length > 0 && args[0].equalsIgnoreCase("check")) { + sender.sendMessage("SilentChest is " + (plugin.getPlayerAnyChestStatus(player) ? "ON" : "OFF") + "."); + return true; + } + + plugin.setPlayerSilentChestStatus(player, !plugin.getPlayerSilentChestStatus(player)); + sender.sendMessage("SilentChest is now " + (plugin.getPlayerSilentChestStatus(player) ? "ON" : "OFF") + "."); + + return true; + } +} diff --git a/plugin/src/main/java/com/lishid/openinv/commands/ToggleOpenInvCommand.java b/plugin/src/main/java/com/lishid/openinv/commands/ToggleOpenInvCommand.java deleted file mode 100644 index dcda462..0000000 --- a/plugin/src/main/java/com/lishid/openinv/commands/ToggleOpenInvCommand.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.commands; - -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.Configuration; - -public class ToggleOpenInvCommand implements CommandExecutor { - - private final OpenInv plugin; - private final Configuration configuration; - - public ToggleOpenInvCommand(OpenInv plugin) { - this.plugin = plugin; - configuration = plugin.getConfiguration(); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (command.getName().equalsIgnoreCase("toggleopeninv")) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "You can't use this command from the console."); - return true; - } - - if (!OpenInv.hasPermission(sender, Permissions.PERM_OPENINV)) { - sender.sendMessage(ChatColor.RED + "You do not have permission to access player inventories."); - return true; - } - - Player player = (Player) sender; - - if (args.length > 0) { - if (args[0].equalsIgnoreCase("check")) { - String status = configuration.getPlayerItemOpenInvStatus(player) ? ChatColor.GREEN + "ON" : ChatColor.RED + "OFF"; - OpenInv.sendMessage(player, "OpenInv with " + ChatColor.GRAY + configuration.getOpenInvItem() + ChatColor.RESET + status + ChatColor.RESET + "."); - return true; - } - } - - configuration.setPlayerItemOpenInvStatus(player, !configuration.getPlayerItemOpenInvStatus(player)); - - String status = configuration.getPlayerItemOpenInvStatus(player) ? ChatColor.GREEN + "ON" : ChatColor.RED + "OFF"; - OpenInv.sendMessage(player, "OpenInv with " + ChatColor.GRAY + configuration.getOpenInvItem() + ChatColor.RESET + " is now " + status + ChatColor.RESET + "."); - - return true; - } - - return false; - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvEntityListener.java b/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvEntityListener.java deleted file mode 100644 index b01a9f4..0000000 --- a/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvEntityListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.listeners; - -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.Configuration; - -public class OpenInvEntityListener implements Listener { - - private final OpenInv plugin; - private final Configuration configuration; - - public OpenInvEntityListener(OpenInv plugin) { - this.plugin = plugin; - configuration = plugin.getConfiguration(); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { - Entity attacker = event.getDamager(); - Entity defender = event.getEntity(); - - if (!(attacker instanceof Player) || !(defender instanceof Player)) { - return; - } - - Player player = (Player) attacker; - - if (player.getInventory().getItemInMainHand().getType() == configuration.getOpenInvItem()) { - if (!configuration.getPlayerItemOpenInvStatus(player) || !OpenInv.hasPermission(player, Permissions.PERM_OPENINV)) { - return; - } - - Player target = (Player) defender; - - event.setDamage(0); - event.setCancelled(true); - - player.performCommand("openinv " + target.getName()); - } - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvInventoryListener.java b/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvInventoryListener.java deleted file mode 100644 index efe92fe..0000000 --- a/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvInventoryListener.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.listeners; - -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; - -import com.lishid.openinv.OpenInv; - -public class OpenInvInventoryListener implements Listener { - - private final OpenInv plugin; - - public OpenInvInventoryListener(OpenInv plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onInventoryClick(InventoryClickEvent event) { - Inventory inventory = event.getInventory(); - HumanEntity player = event.getWhoClicked(); - - if (!plugin.getInventoryAccess().check(inventory, player)) { - event.setCancelled(true); - } - } -} \ No newline at end of file diff --git a/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvPlayerListener.java b/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvPlayerListener.java deleted file mode 100644 index 22495fa..0000000 --- a/plugin/src/main/java/com/lishid/openinv/listeners/OpenInvPlayerListener.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2011-2016 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.listeners; - -import com.lishid.openinv.Configuration; -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; -import com.lishid.openinv.internal.ISpecialEnderChest; -import com.lishid.openinv.internal.ISpecialPlayerInventory; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.Chest; -import org.bukkit.block.Sign; -import org.bukkit.entity.Player; -import org.bukkit.event.Event.Result; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.scheduler.BukkitRunnable; - -public class OpenInvPlayerListener implements Listener { - - private final OpenInv plugin; - private final Configuration configuration; - - public OpenInvPlayerListener(OpenInv plugin) { - this.plugin = plugin; - configuration = plugin.getConfiguration(); - } - - @SuppressWarnings("deprecation") - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerJoin(PlayerJoinEvent event) { - final Player player = event.getPlayer(); - - new BukkitRunnable() { - @Override - public void run() { - if (!player.isOnline()) { - return; - } - - ISpecialPlayerInventory inventory = plugin.getPlayerInventory(player, false); - if (inventory != null) { - inventory.playerOnline(player); - player.updateInventory(); - } - - ISpecialEnderChest enderChest = plugin.getPlayerEnderChest(player, false); - if (enderChest != null) { - enderChest.playerOnline(player); - } - } - }.runTask(plugin); - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - Player player = event.getPlayer(); - - ISpecialPlayerInventory inventory = plugin.getPlayerInventory(player, false); - if (inventory != null) { - inventory.playerOffline(); - if (inventory.isInUse()) { - plugin.removeLoadedInventory(event.getPlayer()); - } - } - - ISpecialEnderChest enderChest = plugin.getPlayerEnderChest(player, false); - if (enderChest != null) { - enderChest.playerOffline(); - if (!enderChest.isInUse()) { - plugin.removeLoadedEnderChest(event.getPlayer()); - } - } - } - - @EventHandler - public void onPlayerInteract(PlayerInteractEvent event) { - Player player = event.getPlayer(); - - if (player.isSneaking()) { - return; - } - - Action action = event.getAction(); - Block block = event.getClickedBlock(); - - switch (action) { - case RIGHT_CLICK_BLOCK: - if (event.useInteractedBlock() == Result.DENY) { - return; - } - - // Ender Chests - if (block.getType() == Material.ENDER_CHEST) { - if (OpenInv.hasPermission(player, Permissions.PERM_SILENT) && configuration.getPlayerSilentChestStatus(player)) { - event.setCancelled(true); - player.openInventory(player.getEnderChest()); - return; - } - } - - // Chests - if (block.getState() instanceof Chest) { - boolean silentChest = false; - boolean anyChest = false; - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); - - if (OpenInv.hasPermission(player, Permissions.PERM_SILENT) && configuration.getPlayerSilentChestStatus(player)) { - silentChest = true; - } - - if (OpenInv.hasPermission(player, Permissions.PERM_ANYCHEST) && configuration.getPlayerAnyChestStatus(player)) { - try { - anyChest = plugin.getAnySilentChest().isAnyChestNeeded(player, x, y, z); - } catch (Exception e) { - player.sendMessage(ChatColor.RED + "Error while executing openinv. Unsupported CraftBukkit."); - e.printStackTrace(); - } - } - - // If the anyChest or silentChest is active - if (anyChest || silentChest) { - if (!plugin.getAnySilentChest().activateChest(player, anyChest, silentChest, x, y, z)) { - event.setCancelled(true); - } - } - - return; - } - - // Signs - if (block.getState() instanceof Sign) { - try { - Sign sign = (Sign) block.getState(); - - if (OpenInv.hasPermission(player, Permissions.PERM_OPENINV) && sign.getLine(0).equalsIgnoreCase("[openinv]")) { - String text = sign.getLine(1).trim() + sign.getLine(2).trim() + sign.getLine(3).trim(); - player.performCommand("openinv " + text); - } - } catch (Exception e) { - player.sendMessage(ChatColor.RED + "An internal error occured."); - e.printStackTrace(); - } - - return; - } - case RIGHT_CLICK_AIR: - // OpenInv item - if (player.getInventory().getItemInMainHand().getType() == configuration.getOpenInvItem() && configuration.getPlayerItemOpenInvStatus(player) && OpenInv.hasPermission(player, Permissions.PERM_OPENINV)) { - player.performCommand("openinv"); - } - } - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/utils/UUIDFetcher.java b/plugin/src/main/java/com/lishid/openinv/utils/UUIDFetcher.java deleted file mode 100644 index cc0499a..0000000 --- a/plugin/src/main/java/com/lishid/openinv/utils/UUIDFetcher.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.lishid.openinv.utils; - -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.Callable; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; - -import com.google.common.collect.ImmutableList; - -public class UUIDFetcher implements Callable> { - - private static final double PROFILES_PER_REQUEST = 100; - private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; - private final JSONParser jsonParser = new JSONParser(); - private final List names; - private final boolean rateLimiting; - - public UUIDFetcher(List names, boolean rateLimiting) { - this.names = ImmutableList.copyOf(names); - this.rateLimiting = rateLimiting; - } - - public UUIDFetcher(List names) { - this(names, true); - } - - @Override - public Map call() throws Exception { - Map uuidMap = new HashMap(); - int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); - - for (int i = 0; i < requests; i++) { - HttpURLConnection connection = createConnection(); - String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); - writeBody(connection, body); - JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); - - for (Object profile : array) { - JSONObject jsonProfile = (JSONObject) profile; - String id = (String) jsonProfile.get("id"); - String name = (String) jsonProfile.get("name"); - UUID uuid = UUIDFetcher.getUUID(id); - uuidMap.put(name.toLowerCase(), uuid); - } - - if (rateLimiting && i != requests - 1) { - Thread.sleep(100L); - } - } - - return uuidMap; - } - - private static void writeBody(HttpURLConnection connection, String body) throws Exception { - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - } - - private static HttpURLConnection createConnection() throws Exception { - URL url = new URL(PROFILE_URL); - - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - - return connection; - } - - private static UUID getUUID(String id) { - return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" +id.substring(20, 32)); - } - - public static byte[] toBytes(UUID uuid) { - ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); - byteBuffer.putLong(uuid.getMostSignificantBits()); - byteBuffer.putLong(uuid.getLeastSignificantBits()); - - return byteBuffer.array(); - } - - public static UUID fromBytes(byte[] array) { - if (array.length != 16) { - throw new IllegalArgumentException("Illegal byte array length: " + array.length); - } - - ByteBuffer byteBuffer = ByteBuffer.wrap(array); - long mostSignificant = byteBuffer.getLong(); - long leastSignificant = byteBuffer.getLong(); - - return new UUID(mostSignificant, leastSignificant); - } - - public static UUID getUUIDOf(String name) throws Exception { - return new UUIDFetcher(Arrays.asList(name)).call().get(name); - } -} diff --git a/plugin/src/main/java/com/lishid/openinv/utils/UUIDUtils.java b/plugin/src/main/java/com/lishid/openinv/utils/UUIDUtils.java deleted file mode 100644 index 0ac6aba..0000000 --- a/plugin/src/main/java/com/lishid/openinv/utils/UUIDUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.lishid.openinv.utils; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.UUID; - -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -public final class UUIDUtils { - - private UUIDUtils() {} - - private static Player getPlayer(String name) { - Validate.notNull(name, "Name cannot be null"); - - Player found = null; - String lowerName = name.toLowerCase(); - int delta = Integer.MAX_VALUE; - - Collection players = Bukkit.getOnlinePlayers(); - for (Player player : players) { - if (player.getName().toLowerCase().startsWith(lowerName)) { - int curDelta = player.getName().length() - lowerName.length(); - - if (curDelta < delta) { - found = player; - delta = curDelta; - } - - if (curDelta == 0) break; - } - } - - return found; - } - - @SuppressWarnings("deprecation") - private static UUID getUUIDLocally(String name) { - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name); - return offlinePlayer.hasPlayedBefore() ? offlinePlayer.getUniqueId() : null; - } - - /** - * Returns the UUID of a player by their name. - * - * @param name the name of the player to get the UUID of - * @return the player's UUID or null - */ - public static UUID getPlayerUUID(String name) { - UUID uuid; - Player player = getPlayer(name); - - if (player != null) { - uuid = player.getUniqueId(); - } else { - if (Bukkit.getServer().getOnlineMode()) { - if (!Bukkit.getServer().isPrimaryThread()) { - UUIDFetcher fetcher = new UUIDFetcher(Arrays.asList(name)); - Map response; - - try { - response = fetcher.call(); - uuid = response.get(name.toLowerCase()); - } catch (Exception e) { - uuid = getUUIDLocally(name); - } - } else { - uuid = getUUIDLocally(name); - } - } else { - uuid = getUUIDLocally(name); - } - } - - return uuid; - } -} diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml deleted file mode 100644 index 50320d5..0000000 --- a/plugin/src/main/resources/config.yml +++ /dev/null @@ -1,6 +0,0 @@ -config-version: 2 -notify: - any-chest: true - silent-chest: true -items: - open-inv: STICK \ No newline at end of file diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentChest.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentChest.java deleted file mode 100644 index ebe3624..0000000 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentChest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2011-2016 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_11_R1; - -import java.util.Iterator; - -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.internal.IAnySilentChest; - -import org.bukkit.entity.Player; - -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.BlockPosition; -import net.minecraft.server.v1_11_R1.Entity; -import net.minecraft.server.v1_11_R1.EntityOcelot; -import net.minecraft.server.v1_11_R1.EntityPlayer; -import net.minecraft.server.v1_11_R1.EnumDirection; -import net.minecraft.server.v1_11_R1.ITileInventory; -import net.minecraft.server.v1_11_R1.InventoryLargeChest; -import net.minecraft.server.v1_11_R1.TileEntity; -import net.minecraft.server.v1_11_R1.TileEntityChest; -import net.minecraft.server.v1_11_R1.World; - -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; - -public class AnySilentChest implements IAnySilentChest { - - private final OpenInv plugin; - - public AnySilentChest(OpenInv plugin) { - this.plugin = plugin; - } - - @Override - public boolean isAnyChestNeeded(Player p, int x, int y, int z) { - // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest - BlockPosition position = new BlockPosition(x, y, z); - EntityPlayer player = ((CraftPlayer) p).getHandle(); - World world = player.world; - BlockChest chest = (BlockChest) (((BlockChest) world.getType(position).getBlock()).g == Type.TRAP ? - Block.getByName("trapped_chest") : Block.getByName("chest")); - - // If a block is on top - if (topBlocking(world, position)) { - return true; - } - - // If the block next to the chest is chest and has a block on top - for (EnumDirection direction : EnumDirectionList.HORIZONTAL) { - BlockPosition sidePosition = position.shift(direction); - Block block = world.getType(sidePosition).getBlock(); - - if (block == chest) { - if (this.topBlocking(world, sidePosition)) { - return true; - } - } - } - - return false; - } - - private boolean topBlocking(World world, BlockPosition position) { - return this.blockOnTop(world, position) || this.ocelotOnTop(world, position); - } - - @SuppressWarnings("deprecation") - private boolean blockOnTop(World world, BlockPosition position) { - Block block = world.getType(position.up()).getBlock(); - return block.isOccluding(block.getBlockData()); - } - - private boolean ocelotOnTop(World world, BlockPosition position) { - Iterator iterator = world.a(EntityOcelot.class, - new AxisAlignedBB(position.getX(), position.getY() + 1, - position.getZ(), position.getX() + 1, - position.getY() + 2, position.getZ() + 1)).iterator(); - - EntityOcelot entityOcelot; - - do { - if (!iterator.hasNext()) { - return false; - } - - Entity entity = (Entity) iterator.next(); - - entityOcelot = (EntityOcelot) entity; - } while (!entityOcelot.isSitting()); - - return true; - } - - @Override - public boolean activateChest(Player p, boolean anyChest, boolean silentChest, int x, int y, int z) { - BlockPosition position = new BlockPosition(x, y, z); - EntityPlayer player = ((CraftPlayer) p).getHandle(); - World world = player.world; - if (world.isClientSide) { - return true; - } - - BlockChest chest = (BlockChest) (((BlockChest) world.getType(position).getBlock()).g == Type.TRAP ? - Block.getByName("trapped_chest") : Block.getByName("chest")); - - TileEntity tileEntity = world.getTileEntity(position); - if (!(tileEntity instanceof TileEntityChest)) { - return true; - } - - ITileInventory tileInventory = (ITileInventory) tileEntity; - if (!anyChest && this.topBlocking(world, position)) { - return true; - } - - for (EnumDirection direction : EnumDirectionList.HORIZONTAL) { - BlockPosition side = position.shift(direction); - Block block = world.getType(side).getBlock(); - - if (block == chest) { - if (!anyChest && this.topBlocking(world, side)) { - return true; - } - - TileEntity sideTileEntity = world.getTileEntity(side); - - if (sideTileEntity instanceof TileEntityChest) { - if (direction != EnumDirection.WEST && direction != EnumDirection.NORTH) { - tileInventory = new InventoryLargeChest("container.chestDouble", tileInventory, (TileEntityChest) sideTileEntity); - } else { - tileInventory = new InventoryLargeChest("container.chestDouble", (TileEntityChest) sideTileEntity, tileInventory); - } - } - } - } - - boolean returnValue = true; - - if (silentChest) { - tileInventory = new SilentInventory(tileInventory); - - if (plugin.getConfiguration().notifySilentChest()) { - OpenInv.sendMessage(p, "You are opening a chest silently."); - } - - returnValue = false; - } - - player.openContainer(tileInventory); - - if (anyChest && plugin.getConfiguration().notifyAnyChest()) { - OpenInv.sendMessage(p, "You are opening a blocked chest."); - } - - return returnValue; - } -} diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentContainer.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentContainer.java new file mode 100644 index 0000000..bd084ba --- /dev/null +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/AnySilentContainer.java @@ -0,0 +1,276 @@ +/* + * 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_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; +import net.minecraft.server.v1_11_R1.Entity; +import net.minecraft.server.v1_11_R1.EntityOcelot; +import net.minecraft.server.v1_11_R1.EntityPlayer; +import net.minecraft.server.v1_11_R1.EnumDirection; +import net.minecraft.server.v1_11_R1.IBlockData; +import net.minecraft.server.v1_11_R1.IInventory; +import net.minecraft.server.v1_11_R1.ITileInventory; +import net.minecraft.server.v1_11_R1.InventoryEnderChest; +import net.minecraft.server.v1_11_R1.InventoryLargeChest; +import net.minecraft.server.v1_11_R1.PacketPlayOutOpenWindow; +import net.minecraft.server.v1_11_R1.StatisticList; +import net.minecraft.server.v1_11_R1.TileEntity; +import net.minecraft.server.v1_11_R1.TileEntityChest; +import net.minecraft.server.v1_11_R1.TileEntityEnderChest; +import net.minecraft.server.v1_11_R1.TileEntityShulkerBox; +import net.minecraft.server.v1_11_R1.World; + +import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; + +public class AnySilentContainer implements IAnySilentContainer { + + @Override + public boolean isAnySilentContainer(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(Player p, org.bukkit.block.Block b) { + EntityPlayer player = ((CraftPlayer) p).getHandle(); + World world = player.world; + BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Block block = world.getType(blockPosition).getBlock(); + + if (block instanceof BlockShulkerBox) { + return isBlockedShulkerBox(world, blockPosition, block); + } + + 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 (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 (isBlockedChest(world, localBlockPosition)) { + return true; + } + } + + return false; + } + + private boolean isBlockedShulkerBox(World world, BlockPosition blockPosition, Block block) { + // For reference, look at net.minecraft.server.BlockShulkerBox + TileEntity tile = world.getTileEntity(blockPosition); + + if (!(tile instanceof TileEntityShulkerBox)) { + return false; + } + + IBlockData iBlockData = block.getBlockData(); + + EnumDirection enumDirection = iBlockData.get(BlockShulkerBox.a); + if (((TileEntityShulkerBox) tile).p() == TileEntityShulkerBox.AnimationPhase.CLOSED) { + AxisAlignedBB axisAlignedBB = BlockShulkerBox.j.b(0.5F * enumDirection.getAdjacentX(), + 0.5F * enumDirection.getAdjacentY(), 0.5F * enumDirection.getAdjacentZ()) + .a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(), + enumDirection.getAdjacentZ()); + + return world.b(axisAlignedBB.a(blockPosition.shift(enumDirection))); + } + + 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); + } + + private boolean hasOcelotOnTop(World world, 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(Player p, boolean silentchest, org.bukkit.block.Block b) { + + EntityPlayer player = ((CraftPlayer) p).getHandle(); + + // Silent ender chest is pretty much API-only + if (silentchest && b.getType() == Material.ENDER_CHEST) { + p.openInventory(p.getEnderChest()); + player.b(StatisticList.X); + return true; + } + + final World world = player.world; + final BlockPosition blockPosition = new BlockPosition(b.getX(), b.getY(), b.getZ()); + Object tile = world.getTileEntity(blockPosition); + + if (tile == null) { + return false; + } + + if (tile instanceof TileEntityEnderChest) { + // Anychest ender chest. See net.minecraft.server.BlockEnderChest + InventoryEnderChest enderChest = player.getEnderChest(); + enderChest.a((TileEntityEnderChest) tile); + player.openContainer(enderChest); + player.b(StatisticList.X); + return true; + } + + if (!(tile instanceof IInventory)) { + return false; + } + + Block block = world.getType(blockPosition).getBlock(); + Container container = null; + + if (block instanceof BlockChest) { + BlockChest blockChest = (BlockChest) block; + + 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 ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) { + tile = new InventoryLargeChest("container.chestDouble", + (TileEntityChest) localTileEntity, (ITileInventory) tile); + } else { + tile = new InventoryLargeChest("container.chestDouble", + (ITileInventory) tile, (TileEntityChest) localTileEntity); + } + break; + } + + if (blockChest.g == Type.BASIC) + player.b(StatisticList.ac); + else if (blockChest.g == Type.TRAP) { + player.b(StatisticList.W); + } + + if (silentchest) { + container = new SilentContainerChest(player.inventory, ((IInventory) tile), player); + } + } + + if (block instanceof BlockShulkerBox) { + player.b(StatisticList.ae); + + if (silentchest && tile instanceof TileEntityShulkerBox) { + // 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); + } + } + + boolean returnValue = false; + final IInventory iInventory = (IInventory) tile; + + if (!silentchest || container == null) { + player.openContainer(iInventory); + returnValue = true; + } else { + try { + int windowId = player.nextContainerCounter(); + 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; + } + +} diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/EnumDirectionList.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/EnumDirectionList.java deleted file mode 100644 index 7236969..0000000 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/EnumDirectionList.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lishid.openinv.internal.v1_11_R1; - -import java.util.Iterator; - -import com.google.common.collect.Iterators; - -import net.minecraft.server.v1_11_R1.EnumDirection; -import net.minecraft.server.v1_11_R1.EnumDirection.EnumDirectionLimit; - -public enum EnumDirectionList implements Iterable { - - HORIZONTAL(EnumDirectionLimit.HORIZONTAL), - VERTICAL(EnumDirectionLimit.VERTICAL); - - private final EnumDirectionLimit list; - - EnumDirectionList(EnumDirectionLimit list) { - this.list = list; - } - - @Override - public Iterator iterator() { - return Iterators.forArray(list.a()); - } -} diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/InventoryAccess.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/InventoryAccess.java index 0dd1061..3de2a2b 100644 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/InventoryAccess.java +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/InventoryAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2016 lishid. All rights reserved. + * 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 @@ -16,61 +16,64 @@ package com.lishid.openinv.internal.v1_11_R1; -import java.lang.reflect.Field; +import com.lishid.openinv.internal.IInventoryAccess; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalAccessor; -import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventory; -import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.Inventory; -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.Permissions; - +// Volatile import net.minecraft.server.v1_11_R1.IInventory; -public class InventoryAccess { +import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventory; - private final OpenInv plugin; +public class InventoryAccess implements IInventoryAccess { - public InventoryAccess(OpenInv plugin) { - this.plugin = plugin; - } - - public boolean check(Inventory inventory, HumanEntity player) { - IInventory inv = grabInventory(inventory); - - if (inv instanceof SpecialPlayerInventory) { - if (!OpenInv.hasPermission(player, Permissions.PERM_EDITINV)) { - return false; - } - } else if (inv instanceof SpecialEnderChest) { - if (!OpenInv.hasPermission(player, Permissions.PERM_EDITENDER)) { - return false; - } - } - - return true; - } - - private IInventory grabInventory(Inventory inventory) { + @Override + public boolean isSpecialPlayerInventory(Inventory inventory) { if (inventory instanceof CraftInventory) { - return ((CraftInventory) inventory).getInventory(); + return ((CraftInventory) inventory).getInventory() instanceof ISpecialPlayerInventory; } - - // Use reflection to find the inventory - Class clazz = inventory.getClass(); - IInventory result = null; - for (Field f : clazz.getDeclaredFields()) { - f.setAccessible(true); - - if (IInventory.class.isAssignableFrom(f.getDeclaringClass())) { - try { - result = (IInventory) f.get(inventory); - } catch (Exception e) { - plugin.log(e); - } - } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialPlayerInventory; + } + + @Override + public ISpecialPlayerInventory getSpecialPlayerInventory(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); } - return result; + if (inv instanceof SpecialPlayerInventory) { + return (SpecialPlayerInventory) inv; + } + return null; } + + @Override + public boolean isSpecialEnderChest(Inventory inventory) { + if (inventory instanceof CraftInventory) { + return ((CraftInventory) inventory).getInventory() instanceof ISpecialEnderChest; + } + return InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory) instanceof ISpecialEnderChest; + } + + @Override + public ISpecialEnderChest getSpecialEnderChest(Inventory inventory) { + IInventory inv; + if (inventory instanceof CraftInventory) { + inv = ((CraftInventory) inventory).getInventory(); + } else { + inv = InternalAccessor.grabFieldOfTypeFromObject(IInventory.class, inventory); + } + + if (inv instanceof SpecialEnderChest) { + return (SpecialEnderChest) inv; + } + return null; + } + } diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/PlayerDataManager.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/PlayerDataManager.java index 0632b89..760fe58 100644 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/PlayerDataManager.java +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/PlayerDataManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2016 lishid. All rights reserved. + * 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 @@ -16,54 +16,49 @@ package com.lishid.openinv.internal.v1_11_R1; -import java.util.UUID; +import com.lishid.openinv.internal.IPlayerDataManager; + +import com.mojang.authlib.GameProfile; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; -import org.bukkit.craftbukkit.v1_11_R1.CraftServer; import org.bukkit.entity.Player; -import com.lishid.openinv.OpenInv; -import com.mojang.authlib.GameProfile; - +// Volatile import net.minecraft.server.v1_11_R1.EntityPlayer; import net.minecraft.server.v1_11_R1.MinecraftServer; import net.minecraft.server.v1_11_R1.PlayerInteractManager; -public class PlayerDataManager { +import org.bukkit.craftbukkit.v1_11_R1.CraftServer; - private final OpenInv plugin; +public class PlayerDataManager implements IPlayerDataManager { - public PlayerDataManager(OpenInv plugin) { - this.plugin = plugin; - } - - public Player loadPlayer(UUID uuid) { - try { - OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); - if (player == null || !player.hasPlayedBefore()) { - return null; - } - - GameProfile profile = new GameProfile(uuid, player.getName()); - MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); - // Create an entity to load the player data - EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, new PlayerInteractManager(server.getWorldServer(0))); - - // Get the bukkit entity - Player target = entity.getBukkitEntity(); - - if (target != null) { - // Load data - target.loadData(); - - // Return the entity - return target; - } - } catch (Exception e) { - plugin.log(e); + @Override + public Player loadPlayer(OfflinePlayer offline) { + // Ensure player has data + if (offline == null || !offline.hasPlayedBefore()) { + return null; } - return null; + // Create a profile and entity to load the player data + GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName()); + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile, + new PlayerInteractManager(server.getWorldServer(0))); + + // Get the bukkit entity + Player target = (entity == null) ? null : entity.getBukkitEntity(); + if (target != null) { + // Load data + target.loadData(); + } + // Return the entity + return target; } + + @Override + public String getPlayerDataID(OfflinePlayer player) { + return player.getUniqueId().toString(); + } + } diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerChest.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerChest.java new file mode 100644 index 0000000..16c15a9 --- /dev/null +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerChest.java @@ -0,0 +1,47 @@ +/* + * 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_11_R1; + +// Volatile +import net.minecraft.server.v1_11_R1.ContainerChest; +import net.minecraft.server.v1_11_R1.EntityHuman; +import net.minecraft.server.v1_11_R1.IInventory; +import net.minecraft.server.v1_11_R1.ItemStack; +import net.minecraft.server.v1_11_R1.PlayerInventory; + +public class SilentContainerChest extends ContainerChest { + + public SilentContainerChest(PlayerInventory playerInventory, IInventory iInventory, + EntityHuman entityHuman) { + super(playerInventory, iInventory, entityHuman); + // Send close signal + iInventory.closeContainer(entityHuman); + } + + @Override + public void b(EntityHuman entityHuman) { + // Don't send close signal twice, might screw up + PlayerInventory playerinventory = entityHuman.inventory; + + if (playerinventory.getCarried() != ItemStack.a) { + ItemStack carried = playerinventory.getCarried(); + playerinventory.setCarried(ItemStack.a); + entityHuman.drop(carried, false); + } + } + +} diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerShulkerBox.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerShulkerBox.java new file mode 100644 index 0000000..9fd4fbf --- /dev/null +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentContainerShulkerBox.java @@ -0,0 +1,56 @@ +package com.lishid.openinv.internal.v1_11_R1; + +import java.lang.reflect.Field; + +import net.minecraft.server.v1_11_R1.ContainerShulkerBox; +import net.minecraft.server.v1_11_R1.EntityHuman; +import net.minecraft.server.v1_11_R1.IInventory; +import net.minecraft.server.v1_11_R1.ItemStack; +import net.minecraft.server.v1_11_R1.PlayerInventory; +import net.minecraft.server.v1_11_R1.TileEntityShulkerBox; + +public class SilentContainerShulkerBox extends ContainerShulkerBox { + + private static Field fieldShulkerActionData; + + public SilentContainerShulkerBox(PlayerInventory playerInventory, IInventory iInventory, + EntityHuman entityHuman) { + super(playerInventory, iInventory, entityHuman); + } + + @Override + public void b(EntityHuman entityHuman) { + PlayerInventory playerinventory = entityHuman.inventory; + + if (!playerinventory.getCarried().isEmpty()) { + entityHuman.drop(playerinventory.getCarried(), false); + playerinventory.setCarried(ItemStack.a); + } + } + + private static Field exposeOpenStatus() throws NoSuchFieldException, SecurityException { + if (fieldShulkerActionData == null) { + fieldShulkerActionData = TileEntityShulkerBox.class.getDeclaredField("h"); + fieldShulkerActionData.setAccessible(true); + } + return fieldShulkerActionData; + } + + public static void setOpenValue(TileEntityShulkerBox tileShulkerBox, Object value) { + try { + exposeOpenStatus().set(tileShulkerBox, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static Integer getOpenValue(TileEntityShulkerBox tileShulkerBox) { + try { + return (Integer) exposeOpenStatus().get(tileShulkerBox); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentInventory.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentInventory.java deleted file mode 100644 index 4786853..0000000 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SilentInventory.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.lishid.openinv.internal.v1_11_R1; - -import java.util.List; - -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftHumanEntity; -import org.bukkit.entity.HumanEntity; -import org.bukkit.inventory.InventoryHolder; - -import net.minecraft.server.v1_11_R1.ChestLock; -import net.minecraft.server.v1_11_R1.Container; -import net.minecraft.server.v1_11_R1.ContainerChest; -import net.minecraft.server.v1_11_R1.EntityHuman; -import net.minecraft.server.v1_11_R1.IChatBaseComponent; -import net.minecraft.server.v1_11_R1.ITileInventory; -import net.minecraft.server.v1_11_R1.ItemStack; -import net.minecraft.server.v1_11_R1.PlayerInventory; - -public class SilentInventory implements ITileInventory { - - public ITileInventory inv; - - public SilentInventory(ITileInventory inv) { - this.inv = inv; - } - - @Override - public boolean isLocked() - { - return inv.isLocked(); - } - - @Override - public void a(ChestLock chestLock) { - inv.a(chestLock); - } - - @Override - public ChestLock getLock() { - return inv.getLock(); - } - - @Override - public int getSize() { - return inv.getSize(); - } - - @Override - public boolean w_() { - return inv.w_(); - } - - @Override - public ItemStack getItem(int i) { - return inv.getItem(i); - } - - @Override - public ItemStack splitStack(int i, int i1) { - return inv.splitStack(i, i1); - } - - @Override - public ItemStack splitWithoutUpdate(int i) { - return inv.splitWithoutUpdate(i); - } - - @Override - public void setItem(int i, ItemStack itemStack) { - inv.setItem(i, itemStack); - } - - @Override - public int getMaxStackSize() { - return inv.getMaxStackSize(); - } - - @Override - public void update() { - inv.update(); - } - - @Override - public boolean a(EntityHuman entityHuman) { - return inv.a(entityHuman); - } - - @Override - public void startOpen(EntityHuman entityHuman) { - // Don't do anything - } - - @Override - public void closeContainer(EntityHuman entityHuman) { - // Don't do anything - } - - @Override - public boolean b(int i, ItemStack itemStack) { - return inv.b(i, itemStack); - } - - @Override - public int getProperty(int i) { - return inv.getProperty(i); - } - - @Override - public void setProperty(int i, int i1) { - inv.setProperty(i, i1); - } - - @Override - public int h() { - return inv.h(); - } - - @Override - public void clear() { - inv.clear(); - } - - @Override - public List getContents() { - return inv.getContents(); - } - - @Override - public void onOpen(CraftHumanEntity craftHumanEntity) { - inv.onOpen(craftHumanEntity); - } - - @Override - public void onClose(CraftHumanEntity craftHumanEntity) { - inv.onClose(craftHumanEntity); - } - - @Override - public List getViewers() { - return inv.getViewers(); - } - - @Override - public InventoryHolder getOwner() { - return inv.getOwner(); - } - - @Override - public void setMaxStackSize(int i) { - inv.setMaxStackSize(i); - } - - @Override - public Location getLocation() { - return inv.getLocation(); - } - - @Override - public String getName() { - return inv.getName(); - } - - @Override - public boolean hasCustomName() { - return inv.hasCustomName(); - } - - @Override - public IChatBaseComponent getScoreboardDisplayName() { - return inv.getScoreboardDisplayName(); - } - - @Override - public Container createContainer(PlayerInventory playerInventory, EntityHuman entityHuman) { - // Don't let the chest itself create the container. - return new ContainerChest(playerInventory, this, entityHuman); - } - - @Override - public String getContainerName() { - return inv.getContainerName(); - } -} diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialEnderChest.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialEnderChest.java index 45e53e2..b533c20 100644 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialEnderChest.java +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialEnderChest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2016 lishid. All rights reserved. + * 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 @@ -17,50 +17,48 @@ package com.lishid.openinv.internal.v1_11_R1; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.List; -import net.minecraft.server.v1_11_R1.NonNullList; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventory; +import com.lishid.openinv.internal.ISpecialEnderChest; + import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; +// Volatile +import net.minecraft.server.v1_11_R1.IInventory; import net.minecraft.server.v1_11_R1.InventoryEnderChest; import net.minecraft.server.v1_11_R1.InventorySubcontainer; import net.minecraft.server.v1_11_R1.ItemStack; -public class SpecialEnderChest extends InventorySubcontainer { +import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventory; + +public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest { - private final CraftInventory inventory = new CraftInventory(this); private final InventoryEnderChest enderChest; - private CraftPlayer owner; - private boolean playerOnline; + private final CraftInventory inventory = new CraftInventory(this); + private boolean playerOnline = false; - public SpecialEnderChest(Player p, boolean online) { - this(p, ((CraftPlayer) p).getHandle().getEnderChest(), online); + public SpecialEnderChest(Player player, Boolean online) { + super(((CraftPlayer) player).getHandle().getEnderChest().getName(), + ((CraftPlayer) player).getHandle().getEnderChest().hasCustomName(), + ((CraftPlayer) player).getHandle().getEnderChest().getSize()); + CraftPlayer craftPlayer = (CraftPlayer) player; + this.enderChest = craftPlayer.getHandle().getEnderChest(); + this.bukkitOwner = craftPlayer; + setItemLists(this, enderChest.getContents()); } - public SpecialEnderChest(Player p, InventoryEnderChest enderChest, boolean online) { - super(enderChest.getName(), enderChest.hasCustomName(), enderChest.getSize()); - this.owner = (CraftPlayer) p; - this.enderChest = enderChest; - this.playerOnline = online; - reflectContents(getClass().getSuperclass(), this, this.enderChest.getContents()); - } - - private void saveOnExit() { - if (transaction.isEmpty() && !playerOnline) { - owner.saveData(); - } - } - - private void reflectContents(Class clazz, InventorySubcontainer enderChest, List items) { + private void setItemLists(InventorySubcontainer subcontainer, List list) { try { - Field itemsField = clazz.getDeclaredField("items"); - itemsField.setAccessible(true); - itemsField.set(enderChest, items); + // Prepare to remove final modifier + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + // Access and replace main inventory array + Field field = InventorySubcontainer.class.getField("items"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(subcontainer, list); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { @@ -72,46 +70,31 @@ public class SpecialEnderChest extends InventorySubcontainer { } } - private void linkInventory(InventoryEnderChest inventory) { - reflectContents(inventory.getClass(), inventory, this.items); - } - + @Override public Inventory getBukkitInventory() { return inventory; } - public boolean inventoryRemovalCheck(boolean save) { - boolean offline = transaction.isEmpty() && !playerOnline; - - if (offline && save) { - owner.saveData(); - } - - return offline; - } - - public void playerOnline(Player p) { + @Override + public void setPlayerOnline(Player player) { if (!playerOnline) { - owner = (CraftPlayer) p; - linkInventory(((CraftPlayer) p).getHandle().getEnderChest()); + try { + this.bukkitOwner = player; + CraftPlayer craftPlayer = (CraftPlayer) player; + setItemLists(craftPlayer.getHandle().getEnderChest(), this.items); + } catch (Exception e) {} playerOnline = true; } } - public boolean playerOffline() { + @Override + public void setPlayerOffline() { playerOnline = false; - return inventoryRemovalCheck(false); } @Override - public void onClose(CraftHumanEntity who) { - super.onClose(who); - inventoryRemovalCheck(true); - } - - @Override - public InventoryHolder getOwner() { - return this.owner; + public boolean isInUse() { + return !this.getViewers().isEmpty(); } @Override @@ -119,4 +102,5 @@ public class SpecialEnderChest extends InventorySubcontainer { super.update(); enderChest.update(); } + } diff --git a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialPlayerInventory.java b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialPlayerInventory.java index a19bfe4..dbd07ed 100644 --- a/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialPlayerInventory.java +++ b/v1_11_R1/src/main/java/com/lishid/openinv/internal/v1_11_R1/SpecialPlayerInventory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2016 lishid. All rights reserved. + * 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 @@ -17,101 +17,94 @@ package com.lishid.openinv.internal.v1_11_R1; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Arrays; + +import com.lishid.openinv.internal.ISpecialPlayerInventory; -import net.minecraft.server.v1_11_R1.*; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventory; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; -public class SpecialPlayerInventory extends PlayerInventory { +import net.minecraft.server.v1_11_R1.ContainerUtil; +// Volatile +import net.minecraft.server.v1_11_R1.EntityHuman; +import net.minecraft.server.v1_11_R1.ItemStack; +import net.minecraft.server.v1_11_R1.NonNullList; +import net.minecraft.server.v1_11_R1.PlayerInventory; + +import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_11_R1.inventory.CraftInventory; + +public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory { private final CraftInventory inventory = new CraftInventory(this); - private final NonNullList extra = NonNullList.a(); - private CraftPlayer owner; - private NonNullList[] arrays; - private boolean playerOnline; + private boolean playerOnline = false; - public SpecialPlayerInventory(Player p, boolean online) { - super(((CraftPlayer) p).getHandle()); - this.owner = (CraftPlayer) p; + public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) { + super(((CraftPlayer) bukkitPlayer).getHandle()); this.playerOnline = online; - reflectContents(getClass().getSuperclass(), player.inventory, this); + setItemArrays(this, player.inventory.items, player.inventory.armor, player.inventory.extraSlots); } - private void reflectContents(Class clazz, PlayerInventory src, PlayerInventory dest) { + private void setItemArrays(PlayerInventory inventory, NonNullList items, + NonNullList armor, NonNullList extraSlots) { try { - Field itemsField = clazz.getDeclaredField("items"); - itemsField.setAccessible(true); - itemsField.set(dest, src.items); + // Prepare to remove final modifier + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); - Field armorField = clazz.getDeclaredField("armor"); - armorField.setAccessible(true); - armorField.set(dest, src.armor); + // Access and replace main inventory array + Field field = PlayerInventory.class.getField("items"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, items); - Field extraSlotsField = clazz.getDeclaredField("extraSlots"); - extraSlotsField.setAccessible(true); - extraSlotsField.set(dest, src.extraSlots); + // Access and replace armor inventory array + field = PlayerInventory.class.getField("armor"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, armor); + + // Access and replace offhand inventory array + field = PlayerInventory.class.getField("extraSlots"); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, extraSlots); + + // Access and replace array containing all inventory arrays + field = PlayerInventory.class.getDeclaredField("g"); + field.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(inventory, Arrays.asList(new NonNullList[] { items, armor, extraSlots })); } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (SecurityException e) { + // Unable to set final fields to item arrays, we're screwed. Noisily fail. e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } - - //noinspection unchecked - arrays = new NonNullList[] { this.items, this.armor, this.extraSlots, this.extra }; - } - - private void linkInventory(PlayerInventory inventory) { - reflectContents(inventory.getClass(), inventory, this); } + @Override public Inventory getBukkitInventory() { return inventory; } - public boolean inventoryRemovalCheck(boolean save) { - boolean offline = transaction.isEmpty() && !playerOnline; - - if (offline && save) { - owner.saveData(); - } - - return offline; - } - - public void playerOnline(Player player) { + @Override + public void setPlayerOnline(Player player) { if (!playerOnline) { - owner = (CraftPlayer) player; - this.player = owner.getHandle(); - linkInventory(owner.getHandle().inventory); + this.player = ((CraftPlayer) player).getHandle(); + setItemArrays(this.player.inventory, items, armor, extraSlots); playerOnline = true; } } - public boolean playerOffline() { + @Override + public void setPlayerOffline() { playerOnline = false; - return inventoryRemovalCheck(false); } @Override - public void onClose(CraftHumanEntity who) { - super.onClose(who); - inventoryRemovalCheck(true); - } - - @Override - public NonNullList getContents() { - NonNullList contents = NonNullList.a(); - contents.addAll(this.items); - contents.addAll(this.armor); - contents.addAll(this.extraSlots); - return contents; + public boolean isInUse() { + return !this.getViewers().isEmpty(); } @Override @@ -121,153 +114,142 @@ public class SpecialPlayerInventory extends PlayerInventory { @Override public ItemStack getItem(int i) { - NonNullList is = null; - NonNullList[] contents = this.arrays; - int j = contents.length; + NonNullList list = this.items; - for (int k = 0; k < j; ++k) { - NonNullList is2 = contents[k]; - - if (i < is2.size()) { - is = is2; - break; - } - - i -= is2.size(); - } - - if (is == this.items) { + if (i >= list.size()) { + i -= list.size(); + list = this.armor; + } else { i = getReversedItemSlotNum(i); - } else if (is == this.armor) { - i = getReversedArmorSlotNum(i); - } else if (is == this.extraSlots) { - // Do nothing - } else if (is == this.extra) { - // Do nothing } - return is == null ? ItemStack.a : is.get(i); + if (i >= list.size()) { + i -= list.size(); + list = this.extraSlots; + } else if (list == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= list.size()) { + return ItemStack.a; + } + + return list.get(i); } @Override public ItemStack splitStack(int i, int j) { - NonNullList is = null; - NonNullList[] contents = this.arrays; - int k = contents.length; + NonNullList list = this.items; - for (int l = 0; l < k; ++l) { - NonNullList is2 = contents[l]; - - if (i < is2.size()) { - is = is2; - break; - } - - i -= is2.size(); - } - - if (is == this.items) { + if (i >= list.size()) { + i -= list.size(); + list = this.armor; + } else { i = getReversedItemSlotNum(i); - } else if (is == this.armor) { - i = getReversedArmorSlotNum(i); - } else if (is == this.extraSlots) { - // Do nothing - } else if (is == this.extra) { - // Do nothing } - return is != null && !is.get(i).isEmpty() ? ContainerUtil.a(is, i, j) : ItemStack.a; + if (i >= list.size()) { + i -= list.size(); + list = this.extraSlots; + } else if (list == this.armor) { + i = getReversedArmorSlotNum(i); + } + + if (i >= list.size()) { + return ItemStack.a; + } + + return list == null || list.get(i).isEmpty() ? ItemStack.a : ContainerUtil.a(list, i, j); } @Override public ItemStack splitWithoutUpdate(int i) { - NonNullList is = null; - NonNullList[] contents = this.arrays; - int j = contents.length; + NonNullList list = this.items; - for (int object = 0; object < j; ++object) { - NonNullList is2 = contents[object]; - - if (i < is2.size()) { - is = is2; - break; - } - - i -= is2.size(); + if (i >= list.size()) { + i -= list.size(); + list = this.armor; + } else { + i = getReversedItemSlotNum(i); } - if (is != null && !is.get(i).isEmpty()) { - if (is == this.items) { - i = getReversedItemSlotNum(i); - } else if (is == this.armor) { - i = getReversedArmorSlotNum(i); - } else if (is == this.extraSlots) { - // Do nothing - } else if (is == this.extra) { - // Do nothing - } + if (i >= list.size()) { + i -= list.size(); + list = this.extraSlots; + } else if (list == this.armor) { + i = getReversedArmorSlotNum(i); + } - Object object = is.get(i); - is.set(i, ItemStack.a); - return (ItemStack) object; - } else { + if (i >= list.size()) { return ItemStack.a; } + + if (list != null && !list.get(i).isEmpty()) { + ItemStack itemstack = list.get(i); + + list.set(i, ItemStack.a); + return itemstack; + } + + return ItemStack.a; } @Override - public void setItem(int i, ItemStack itemStack) { - NonNullList is = null; - NonNullList[] contents = this.arrays; - int j = contents.length; + public void setItem(int i, ItemStack itemstack) { + NonNullList list = this.items; - for (int k = 0; k < j; ++k) { - NonNullList is2 = contents[k]; - - if (i < is2.size()) { - is = is2; - break; - } - - i -= is2.size(); + if (i >= list.size()) { + i -= list.size(); + list = this.armor; + } else { + i = getReversedItemSlotNum(i); } - if (is != null) { - if (is == this.items) { - i = getReversedItemSlotNum(i); - } else if (is == this.armor) { - i = getReversedArmorSlotNum(i); - } else if (is == this.extraSlots) { - // Do nothing - } else if (is == this.extra) { - owner.getHandle().drop(itemStack, true); - itemStack = ItemStack.a; - } + if (i >= list.size()) { + i -= list.size(); + list = this.extraSlots; + } else if (list == this.armor) { + i = getReversedArmorSlotNum(i); + } - is.set(i, itemStack); + if (i >= list.size()) { + player.drop(itemstack, true); + return; + } - owner.getHandle().defaultContainer.b(); + if (list != null) { + list.set(i, itemstack); } } private int getReversedItemSlotNum(int i) { - return (i >= 27) ? (i - 27) : (i + 9); + if (i >= 27) { + return i - 27; + } + return i + 9; } private int getReversedArmorSlotNum(int i) { - if (i == 0) return 3; - if (i == 1) return 2; - if (i == 2) return 1; - return (i == 3) ? 0 : i; - } - - @Override - public boolean hasCustomName() { - return true; + if (i == 0) { + return 3; + } + if (i == 1) { + return 2; + } + if (i == 2) { + return 1; + } + if (i == 3) { + return 0; + } + return i; } @Override public String getName() { + if (player.getName().length() > 16) { + return player.getName().substring(0, 16); + } return player.getName(); } @@ -276,9 +258,4 @@ public class SpecialPlayerInventory extends PlayerInventory { return true; } - @Override - public void update() { - super.update(); - player.inventory.update(); - } }