From 5add51bf21872748c35530494c57974d70434071 Mon Sep 17 00:00:00 2001 From: lishid Date: Thu, 28 Jun 2012 10:53:11 -0400 Subject: [PATCH] Fixed all Offline OpenInv related bugs. Thanks to Balor/Belphemur for the most part of the code. --- .classpath | 1 - .settings/org.eclipse.jdt.core.prefs | 12 - src/lishid/openinv/OpenInv.java | 133 ++-- src/lishid/openinv/OpenInvEntityListener.java | 63 +- src/lishid/openinv/OpenInvPlayerListener.java | 352 ++++++----- .../commands/AnyChestPluginCommand.java | 52 +- .../commands/OpenInvPluginCommand.java | 310 ++++++---- .../commands/SearchInvPluginCommand.java | 65 +- .../commands/SilentChestPluginCommand.java | 52 +- .../commands/ToggleOpenInvPluginCommand.java | 63 +- src/lishid/openinv/utils/Metrics.java | 575 ++++++++++++------ ...Chest.java => OpenInvPlayerInventory.java} | 228 ++++--- .../openinv/utils/SilentContainerChest.java | 22 +- src/plugin.yml | 2 +- 14 files changed, 1100 insertions(+), 830 deletions(-) delete mode 100644 .settings/org.eclipse.jdt.core.prefs rename src/lishid/openinv/utils/{PlayerInventoryChest.java => OpenInvPlayerInventory.java} (59%) diff --git a/.classpath b/.classpath index 06906ad..63793d0 100644 --- a/.classpath +++ b/.classpath @@ -5,7 +5,6 @@ - diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index a955402..0000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Tue Apr 26 23:51:01 EDT 2011 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/lishid/openinv/OpenInv.java b/src/lishid/openinv/OpenInv.java index 57c46e1..bf615fd 100644 --- a/src/lishid/openinv/OpenInv.java +++ b/src/lishid/openinv/OpenInv.java @@ -16,8 +16,11 @@ package lishid.openinv; +import java.util.HashMap; + import lishid.openinv.commands.*; import lishid.openinv.utils.Metrics; +import lishid.openinv.utils.OpenInvPlayerInventory; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -27,121 +30,129 @@ import org.bukkit.plugin.java.JavaPlugin; /** * Open other player's inventory - * + * * @author lishid */ -public class OpenInv extends JavaPlugin { - private final OpenInvPlayerListener playerListener = new OpenInvPlayerListener(this); - private final OpenInvEntityListener entityListener = new OpenInvEntityListener(this); - public static OpenInv mainPlugin; - private static Metrics metrics; - - public void onDisable() { +public class OpenInv extends JavaPlugin +{ + private final OpenInvPlayerListener playerListener = new OpenInvPlayerListener(this); + private final OpenInvEntityListener entityListener = new OpenInvEntityListener(this); + public static HashMap inventories = new HashMap(); + public static OpenInv mainPlugin; + private static Metrics metrics; + + public void onDisable() + { + PluginDescriptionFile pdfFile = this.getDescription(); + System.out.println("[" + pdfFile.getName() + "] version " + pdfFile.getVersion() + " disabled!"); } - - public void onEnable() { - mainPlugin = this; - mainPlugin.getConfig().addDefault("ItemOpenInvItemID", 280); - mainPlugin.getConfig().options().copyDefaults(true); - mainPlugin.saveConfig(); - - PluginManager pm = getServer().getPluginManager(); - pm.registerEvents(playerListener, this); - pm.registerEvents(entityListener, this); - - + + public void onEnable() + { + mainPlugin = this; + mainPlugin.getConfig().addDefault("ItemOpenInvItemID", 280); + mainPlugin.getConfig().options().copyDefaults(true); + mainPlugin.saveConfig(); + + PluginManager pm = getServer().getPluginManager(); + pm.registerEvents(playerListener, this); + pm.registerEvents(entityListener, this); + getCommand("openinv").setExecutor(new OpenInvPluginCommand(this)); getCommand("searchinv").setExecutor(new SearchInvPluginCommand(this)); getCommand("toggleopeninv").setExecutor(new ToggleOpenInvPluginCommand()); getCommand("silentchest").setExecutor(new SilentChestPluginCommand(this)); getCommand("anychest").setExecutor(new AnyChestPluginCommand(this)); - //Metrics - try - { - metrics = new Metrics(this); - metrics.start(); - } - catch(Exception e){ e.printStackTrace(); } - + // Metrics + try + { + metrics = new Metrics(this); + metrics.start(); + } + catch (Exception e) + { + e.printStackTrace(); + } + PluginDescriptionFile pdfFile = this.getDescription(); - System.out.println("[" + pdfFile.getName() + "] version " + pdfFile.getVersion() + " enabled!" ); + System.out.println("[" + pdfFile.getName() + "] version " + pdfFile.getVersion() + " enabled!"); } public static boolean GetPlayerItemOpenInvStatus(String name) { - return mainPlugin.getConfig().getBoolean("ItemOpenInv." + name.toLowerCase() + ".toggle", false); + return mainPlugin.getConfig().getBoolean("ItemOpenInv." + name.toLowerCase() + ".toggle", false); } public static void SetPlayerItemOpenInvStatus(String name, boolean status) { - mainPlugin.getConfig().set("ItemOpenInv." + name.toLowerCase() + ".toggle", status); - mainPlugin.saveConfig(); + mainPlugin.getConfig().set("ItemOpenInv." + name.toLowerCase() + ".toggle", status); + mainPlugin.saveConfig(); } - + public static boolean GetPlayerSilentChestStatus(String name) { - return mainPlugin.getConfig().getBoolean("SilentChest." + name.toLowerCase() + ".toggle", false); + return mainPlugin.getConfig().getBoolean("SilentChest." + name.toLowerCase() + ".toggle", false); } public static void SetPlayerSilentChestStatus(String name, boolean status) { - mainPlugin.getConfig().set("SilentChest." + name.toLowerCase() + ".toggle", status); - mainPlugin.saveConfig(); + mainPlugin.getConfig().set("SilentChest." + name.toLowerCase() + ".toggle", status); + mainPlugin.saveConfig(); } - + public static boolean GetPlayerAnyChestStatus(String name) { - return mainPlugin.getConfig().getBoolean("AnyChest." + name.toLowerCase() + ".toggle", true); + return mainPlugin.getConfig().getBoolean("AnyChest." + name.toLowerCase() + ".toggle", true); } public static void SetPlayerAnyChestStatus(String name, boolean status) { - mainPlugin.getConfig().set("AnyChest." + name.toLowerCase() + ".toggle", status); - mainPlugin.saveConfig(); + mainPlugin.getConfig().set("AnyChest." + name.toLowerCase() + ".toggle", status); + mainPlugin.saveConfig(); } public static int GetItemOpenInvItem() { - if(mainPlugin.getConfig().get("ItemOpenInvItemID") == null) - { - SaveToConfig("ItemOpenInvItemID", 280); - } - return mainPlugin.getConfig().getInt("ItemOpenInvItemID", 280); + if (mainPlugin.getConfig().get("ItemOpenInvItemID") == null) + { + SaveToConfig("ItemOpenInvItemID", 280); + } + return mainPlugin.getConfig().getInt("ItemOpenInvItemID", 280); } public static Object GetFromConfig(String data, Object defaultValue) { - Object val = mainPlugin.getConfig().get(data); + Object val = mainPlugin.getConfig().get(data); if (val == null) { - mainPlugin.getConfig().set(data, defaultValue); + mainPlugin.getConfig().set(data, defaultValue); return defaultValue; } else { - return val; + return val; } } public static void SaveToConfig(String data, Object value) { - mainPlugin.getConfig().set(data, value); - mainPlugin.saveConfig(); + mainPlugin.getConfig().set(data, value); + mainPlugin.saveConfig(); } public static void ShowHelp(Player player) { - player.sendMessage(ChatColor.GREEN + "/openinv - Open a player's inventory"); - player.sendMessage(ChatColor.GREEN + " (aliases: oi, inv, open)"); - player.sendMessage(ChatColor.GREEN + "/toggleopeninv - Toggle item openinv function"); - player.sendMessage(ChatColor.GREEN + " (aliases: toi, toggleoi, toggleinv)"); - player.sendMessage(ChatColor.GREEN + "/searchinv [MinAmount] - "); - player.sendMessage(ChatColor.GREEN + " Search and list players having a specific item."); - player.sendMessage(ChatColor.GREEN + " (aliases: si, search)"); - player.sendMessage(ChatColor.GREEN + "/anychest - Toggle anychest function"); - player.sendMessage(ChatColor.GREEN + " (aliases: ac)"); - player.sendMessage(ChatColor.GREEN + "/silentchest - Toggle silent chest function"); - player.sendMessage(ChatColor.GREEN + " (aliases: sc, silent)"); + player.sendMessage(ChatColor.GREEN + "/openinv - Open a player's inventory"); + player.sendMessage(ChatColor.GREEN + " (aliases: oi, inv, open)"); + player.sendMessage(ChatColor.GREEN + "/toggleopeninv - Toggle item openinv function"); + player.sendMessage(ChatColor.GREEN + " (aliases: toi, toggleoi, toggleinv)"); + player.sendMessage(ChatColor.GREEN + "/searchinv [MinAmount] - "); + player.sendMessage(ChatColor.GREEN + " Search and list players having a specific item."); + player.sendMessage(ChatColor.GREEN + " (aliases: si, search)"); + player.sendMessage(ChatColor.GREEN + "/anychest - Toggle anychest function"); + player.sendMessage(ChatColor.GREEN + " (aliases: ac)"); + player.sendMessage(ChatColor.GREEN + "/silentchest - Toggle silent chest function"); + player.sendMessage(ChatColor.GREEN + " (aliases: sc, silent)"); } } \ No newline at end of file diff --git a/src/lishid/openinv/OpenInvEntityListener.java b/src/lishid/openinv/OpenInvEntityListener.java index 9d3bac9..b5634a8 100644 --- a/src/lishid/openinv/OpenInvEntityListener.java +++ b/src/lishid/openinv/OpenInvEntityListener.java @@ -24,38 +24,41 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -public class OpenInvEntityListener implements Listener{ - OpenInv plugin; - public OpenInvEntityListener(OpenInv scrap) { - plugin = scrap; - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onEntityDamage(EntityDamageEvent event) { - if (event instanceof EntityDamageByEntityEvent) { - EntityDamageByEntityEvent evt = (EntityDamageByEntityEvent) event; +public class OpenInvEntityListener implements Listener +{ + OpenInv plugin; + + public OpenInvEntityListener(OpenInv scrap) + { + plugin = scrap; + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onEntityDamage(EntityDamageEvent event) + { + if (event instanceof EntityDamageByEntityEvent) + { + EntityDamageByEntityEvent evt = (EntityDamageByEntityEvent) event; Entity attacker = evt.getDamager(); Entity defender = evt.getEntity(); - - if(!(attacker instanceof Player)||!(defender instanceof Player)) - { - return; - } - - Player player = (Player)attacker; - - if(!(player.getItemInHand().getType().getId() == OpenInv.GetItemOpenInvItem()) - || (!OpenInv.GetPlayerItemOpenInvStatus(player.getName())) - || !player.hasPermission("OpenInv.openinv")) - { - return; - } - - Player target = (Player)defender; - player.performCommand("openinv " + target.getName()); - - evt.setDamage(0); - evt.setCancelled(true); + + if (!(attacker instanceof Player) || !(defender instanceof Player)) + { + return; + } + + Player player = (Player) attacker; + + if (!(player.getItemInHand().getType().getId() == OpenInv.GetItemOpenInvItem()) || (!OpenInv.GetPlayerItemOpenInvStatus(player.getName())) || !player.hasPermission("OpenInv.openinv")) + { + return; + } + + Player target = (Player) defender; + player.performCommand("openinv " + target.getName()); + + evt.setDamage(0); + evt.setCancelled(true); } } } diff --git a/src/lishid/openinv/OpenInvPlayerListener.java b/src/lishid/openinv/OpenInvPlayerListener.java index e741339..5e37f55 100644 --- a/src/lishid/openinv/OpenInvPlayerListener.java +++ b/src/lishid/openinv/OpenInvPlayerListener.java @@ -18,14 +18,13 @@ package lishid.openinv; import java.lang.reflect.Field; -import lishid.openinv.commands.OpenInvPluginCommand; +import lishid.openinv.utils.OpenInvPlayerInventory; import lishid.openinv.utils.SilentContainerChest; import net.minecraft.server.Block; import net.minecraft.server.EntityPlayer; import net.minecraft.server.IInventory; import net.minecraft.server.InventoryLargeChest; import net.minecraft.server.Packet100OpenWindow; -import net.minecraft.server.Packet101CloseWindow; import net.minecraft.server.TileEntityChest; import net.minecraft.server.World; @@ -40,170 +39,189 @@ import org.bukkit.event.Event.Result; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; -public class OpenInvPlayerListener implements Listener{ - OpenInv plugin; - public OpenInvPlayerListener(OpenInv scrap) { - plugin = scrap; - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerLogin(PlayerLoginEvent event) - { - try{ - for(Player target : OpenInvPluginCommand.offlineInv.keySet()) - { - if(target.getName().equalsIgnoreCase(event.getPlayer().getName())) - { - ((CraftPlayer)OpenInvPluginCommand.offlineInv.get(target).Opener).getHandle().netServerHandler.sendPacket(new Packet101CloseWindow()); - target.saveData(); - OpenInvPluginCommand.offlineInv.remove(target); - event.getPlayer().loadData(); - return; - } - } - } - catch(Exception e){} - } - - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerInteract(PlayerInteractEvent event) - { - if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.useInteractedBlock() == Result.DENY) - return; - - if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Chest) - { - boolean silentchest = false; - boolean anychest = false; - int x = event.getClickedBlock().getX(); - int y = event.getClickedBlock().getY(); - int z = event.getClickedBlock().getZ(); - - if(event.getPlayer().hasPermission("OpenInv.silent") && OpenInv.GetPlayerSilentChestStatus(event.getPlayer().getName())) - { - silentchest = true; - } - - if(event.getPlayer().hasPermission("OpenInv.anychest") && OpenInv.GetPlayerAnyChestStatus(event.getPlayer().getName())) - { - try - { - //FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest - EntityPlayer player = ((CraftPlayer)event.getPlayer()).getHandle(); - World world = player.world; - //If block on top - if(world.e(x, y + 1, z)) - anychest = true; - - //If block next to chest is chest and has a block on top - if ((world.getTypeId(x - 1, y, z) == Block.CHEST.id) && (world.e(x - 1, y + 1, z))) - anychest = true; - if ((world.getTypeId(x + 1, y, z) == Block.CHEST.id) && (world.e(x + 1, y + 1, z))) - anychest = true; - if ((world.getTypeId(x, y, z - 1) == Block.CHEST.id) && (world.e(x, y + 1, z - 1))) - anychest = true; - if ((world.getTypeId(x, y, z + 1) == Block.CHEST.id) && (world.e(x, y + 1, z + 1))) - anychest = true; - } - catch(Exception e) - { - event.getPlayer().sendMessage(ChatColor.RED + "Error while executing openinv. Unsupported CraftBukkit."); - e.printStackTrace(); - } - } - - //If the anychest or silentchest is active - if(anychest || silentchest) - { - EntityPlayer player = ((CraftPlayer)event.getPlayer()).getHandle(); - World world = player.world; - Object chest = (TileEntityChest)world.getTileEntity(x, y, z); - if (chest == null) return; - - if(!anychest) - { - if (world.e(x, y + 1, z)) return; - if ((world.getTypeId(x - 1, y, z) == Block.CHEST.id) && (world.e(x - 1, y + 1, z))) return; - if ((world.getTypeId(x + 1, y, z) == Block.CHEST.id) && (world.e(x + 1, y + 1, z))) return; - if ((world.getTypeId(x, y, z - 1) == Block.CHEST.id) && (world.e(x, y + 1, z - 1))) return; - if ((world.getTypeId(x, y, z + 1) == Block.CHEST.id) && (world.e(x, y + 1, z + 1))) return; - } - - if (world.getTypeId(x - 1, y, z) == Block.CHEST.id) chest = new InventoryLargeChest("Large chest", (TileEntityChest)world.getTileEntity(x - 1, y, z), (IInventory)chest); - if (world.getTypeId(x + 1, y, z) == Block.CHEST.id) chest = new InventoryLargeChest("Large chest", (IInventory)chest, (TileEntityChest)world.getTileEntity(x + 1, y, z)); - if (world.getTypeId(x, y, z - 1) == Block.CHEST.id) chest = new InventoryLargeChest("Large chest", (TileEntityChest)world.getTileEntity(x, y, z - 1), (IInventory)chest); - if (world.getTypeId(x, y, z + 1) == Block.CHEST.id) chest = new InventoryLargeChest("Large chest", (IInventory)chest, (TileEntityChest)world.getTileEntity(x, y, z + 1)); - - if(!silentchest) - { - player.openContainer((IInventory)chest); - } - else - { - try{ - int id = 0; - try{ - Field windowID = player.getClass().getDeclaredField("containerCounter"); - windowID.setAccessible(true); - id = windowID.getInt(player); - id = id % 100 + 1; - windowID.setInt(player, id); - } - catch(NoSuchFieldException e) - { } - - player.netServerHandler.sendPacket(new Packet100OpenWindow(id, 0, ((IInventory)chest).getName(), ((IInventory)chest).getSize())); - player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory)chest)); - player.activeContainer.windowId = id; - player.activeContainer.addSlotListener(player); - //event.getPlayer().sendMessage("You are opening a chest silently."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - } - catch(Exception e) - { - e.printStackTrace(); - event.getPlayer().sendMessage(ChatColor.RED + "Error while sending silent chest."); - } - } - - if(anychest) - event.getPlayer().sendMessage("You are opening a blocked chest."); - } - } - - if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Sign) - { - Player player = event.getPlayer(); - try{ - Sign sign = ((Sign)event.getClickedBlock().getState()); - if (player.hasPermission("OpenInv.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 ex) - { - player.sendMessage("Internal Error."); - ex.printStackTrace(); - } - } - - if(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) - { - Player player = event.getPlayer(); - - if(!(player.getItemInHand().getType().getId() == OpenInv.GetItemOpenInvItem()) - || (!OpenInv.GetPlayerItemOpenInvStatus(player.getName())) - || !player.hasPermission("OpenInv.openinv")) - { - return; - } - - player.performCommand("openinv"); - } - } +public class OpenInvPlayerListener implements Listener +{ + OpenInv plugin; + + public OpenInvPlayerListener(OpenInv plugin) + { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerJoin(PlayerJoinEvent event) + { + OpenInvPlayerInventory inventory = OpenInv.inventories.get(event.getPlayer().getName().toLowerCase()); + + if (inventory != null) + { + inventory.PlayerGoOnline((CraftPlayer) event.getPlayer()); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) + { + OpenInvPlayerInventory inventory = OpenInv.inventories.get(event.getPlayer().getName().toLowerCase()); + if(inventory != null) + { + inventory.PlayerGoOffline(); + inventory.InventoryRemovalCheck(); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerInteract(PlayerInteractEvent event) + { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.useInteractedBlock() == Result.DENY) + return; + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Chest) + { + boolean silentchest = false; + boolean anychest = false; + int x = event.getClickedBlock().getX(); + int y = event.getClickedBlock().getY(); + int z = event.getClickedBlock().getZ(); + + if (event.getPlayer().hasPermission("OpenInv.silent") && OpenInv.GetPlayerSilentChestStatus(event.getPlayer().getName())) + { + silentchest = true; + } + + if (event.getPlayer().hasPermission("OpenInv.anychest") && OpenInv.GetPlayerAnyChestStatus(event.getPlayer().getName())) + { + try + { + // FOR REFERENCE, LOOK AT net.minecraft.server.BlockChest + EntityPlayer player = ((CraftPlayer) event.getPlayer()).getHandle(); + World world = player.world; + // If block on top + if (world.e(x, y + 1, z)) + anychest = true; + + // If block next to chest is chest and has a block on top + if ((world.getTypeId(x - 1, y, z) == Block.CHEST.id) && (world.e(x - 1, y + 1, z))) + anychest = true; + if ((world.getTypeId(x + 1, y, z) == Block.CHEST.id) && (world.e(x + 1, y + 1, z))) + anychest = true; + if ((world.getTypeId(x, y, z - 1) == Block.CHEST.id) && (world.e(x, y + 1, z - 1))) + anychest = true; + if ((world.getTypeId(x, y, z + 1) == Block.CHEST.id) && (world.e(x, y + 1, z + 1))) + anychest = true; + } + catch (Exception e) + { + event.getPlayer().sendMessage(ChatColor.RED + "Error while executing openinv. Unsupported CraftBukkit."); + e.printStackTrace(); + } + } + + // If the anychest or silentchest is active + if (anychest || silentchest) + { + EntityPlayer player = ((CraftPlayer) event.getPlayer()).getHandle(); + World world = player.world; + Object chest = (TileEntityChest) world.getTileEntity(x, y, z); + if (chest == null) + return; + + if (!anychest) + { + if (world.e(x, y + 1, z)) + return; + if ((world.getTypeId(x - 1, y, z) == Block.CHEST.id) && (world.e(x - 1, y + 1, z))) + return; + if ((world.getTypeId(x + 1, y, z) == Block.CHEST.id) && (world.e(x + 1, y + 1, z))) + return; + if ((world.getTypeId(x, y, z - 1) == Block.CHEST.id) && (world.e(x, y + 1, z - 1))) + return; + if ((world.getTypeId(x, y, z + 1) == Block.CHEST.id) && (world.e(x, y + 1, z + 1))) + return; + } + + if (world.getTypeId(x - 1, y, z) == Block.CHEST.id) + chest = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(x - 1, y, z), (IInventory) chest); + if (world.getTypeId(x + 1, y, z) == Block.CHEST.id) + chest = new InventoryLargeChest("Large chest", (IInventory) chest, (TileEntityChest) world.getTileEntity(x + 1, y, z)); + if (world.getTypeId(x, y, z - 1) == Block.CHEST.id) + chest = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(x, y, z - 1), (IInventory) chest); + if (world.getTypeId(x, y, z + 1) == Block.CHEST.id) + chest = new InventoryLargeChest("Large chest", (IInventory) chest, (TileEntityChest) world.getTileEntity(x, y, z + 1)); + + if (!silentchest) + { + player.openContainer((IInventory) chest); + } + else + { + try + { + int id = 0; + try + { + Field windowID = player.getClass().getDeclaredField("containerCounter"); + windowID.setAccessible(true); + id = windowID.getInt(player); + id = id % 100 + 1; + windowID.setInt(player, id); + } + catch (NoSuchFieldException e) + { + } + + player.netServerHandler.sendPacket(new Packet100OpenWindow(id, 0, ((IInventory) chest).getName(), ((IInventory) chest).getSize())); + player.activeContainer = new SilentContainerChest(player.inventory, ((IInventory) chest)); + player.activeContainer.windowId = id; + player.activeContainer.addSlotListener(player); + // event.getPlayer().sendMessage("You are opening a chest silently."); + event.setUseInteractedBlock(Result.DENY); + event.setCancelled(true); + } + catch (Exception e) + { + e.printStackTrace(); + event.getPlayer().sendMessage(ChatColor.RED + "Error while sending silent chest."); + } + } + + if (anychest) + event.getPlayer().sendMessage("You are opening a blocked chest."); + } + } + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Sign) + { + Player player = event.getPlayer(); + try + { + Sign sign = ((Sign) event.getClickedBlock().getState()); + if (player.hasPermission("OpenInv.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 ex) + { + player.sendMessage("Internal Error."); + ex.printStackTrace(); + } + } + + if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) + { + Player player = event.getPlayer(); + + if (!(player.getItemInHand().getType().getId() == OpenInv.GetItemOpenInvItem()) || (!OpenInv.GetPlayerItemOpenInvStatus(player.getName())) || !player.hasPermission("OpenInv.openinv")) + { + return; + } + + player.performCommand("openinv"); + } + } } \ No newline at end of file diff --git a/src/lishid/openinv/commands/AnyChestPluginCommand.java b/src/lishid/openinv/commands/AnyChestPluginCommand.java index 8e22ba9..910b1f4 100644 --- a/src/lishid/openinv/commands/AnyChestPluginCommand.java +++ b/src/lishid/openinv/commands/AnyChestPluginCommand.java @@ -24,36 +24,40 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class AnyChestPluginCommand implements CommandExecutor { - public AnyChestPluginCommand(OpenInv plugin) { - +public class AnyChestPluginCommand implements CommandExecutor +{ + public AnyChestPluginCommand(OpenInv plugin) + { + } - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) - { + 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 (!sender.hasPermission("OpenInv.anychest")) { + return true; + } + if (!sender.hasPermission("OpenInv.anychest")) + { sender.sendMessage(ChatColor.RED + "You do not have permission to use anychest."); return true; } - - if(args.length > 0) - { - if(args[0].equalsIgnoreCase("check")) - { - if(OpenInv.GetPlayerAnyChestStatus(sender.getName())) - sender.sendMessage("AnyChest is ON."); - else - sender.sendMessage("AnyChest is OFF."); - } - } - - OpenInv.SetPlayerAnyChestStatus(sender.getName(), !OpenInv.GetPlayerAnyChestStatus(sender.getName())); - sender.sendMessage("AnyChest is now " + (OpenInv.GetPlayerAnyChestStatus(sender.getName())?"On":"Off") + "."); - + + if (args.length > 0) + { + if (args[0].equalsIgnoreCase("check")) + { + if (OpenInv.GetPlayerAnyChestStatus(sender.getName())) + sender.sendMessage("AnyChest is ON."); + else + sender.sendMessage("AnyChest is OFF."); + } + } + + OpenInv.SetPlayerAnyChestStatus(sender.getName(), !OpenInv.GetPlayerAnyChestStatus(sender.getName())); + sender.sendMessage("AnyChest is now " + (OpenInv.GetPlayerAnyChestStatus(sender.getName()) ? "On" : "Off") + "."); + return true; } } diff --git a/src/lishid/openinv/commands/OpenInvPluginCommand.java b/src/lishid/openinv/commands/OpenInvPluginCommand.java index eaa21e4..2480d74 100644 --- a/src/lishid/openinv/commands/OpenInvPluginCommand.java +++ b/src/lishid/openinv/commands/OpenInvPluginCommand.java @@ -17,10 +17,12 @@ package lishid.openinv.commands; import java.io.File; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import lishid.openinv.OpenInv; -import lishid.openinv.utils.PlayerInventoryChest; +import lishid.openinv.utils.OpenInvPlayerInventory; import net.minecraft.server.EntityPlayer; import net.minecraft.server.ItemInWorldManager; @@ -35,153 +37,191 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; -public class OpenInvPluginCommand implements CommandExecutor { +public class OpenInvPluginCommand implements CommandExecutor +{ private final OpenInv plugin; - public static HashMap offlineInv = new HashMap(); + public static HashMap offlineInv = new HashMap(); public static HashMap openInvHistory = new HashMap(); - public OpenInvPluginCommand(OpenInv plugin) { + + public OpenInvPluginCommand(OpenInv plugin) + { this.plugin = plugin; } - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) - { + 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 (!sender.hasPermission("OpenInv.openinv")) { + return true; + } + if (!sender.hasPermission("OpenInv.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((Player)sender); - return true; - } - Player player = (Player)sender; - boolean Offline = false; - - //History management - String history = openInvHistory.get(player); - - if(history == null || history == "") - { - history = player.getName(); - openInvHistory.put(player, history); - } - - //Target selecting - Player target; - - String name = ""; - - //Read from history if target is not named - if (args.length < 1) { - if(history != null && history != "") - { - name = history; - } - else - { - sender.sendMessage(ChatColor.RED + "OpenInv history is empty!"); - return true; - } - } - else - { - name = args[0]; - } - - target = this.plugin.getServer().getPlayer(name); - - if(target == null) - { - //Offline inv here... - try{ - //See if the player has data files - - // Find the player folder - File playerfolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "players"); - - // Find player name - for (File playerfile : playerfolder.listFiles()) - { - String filename = playerfile.getName(); - String playername = filename.substring(0, filename.length() - 4); - - if(playername.trim().equalsIgnoreCase(name)) - { - //Create an entity to load the player data - MinecraftServer server = ((CraftServer)this.plugin.getServer()).getServer(); - EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), playername, new ItemInWorldManager(server.getWorldServer(0))); - target = (entity == null) ? null : (Player) entity.getBukkitEntity(); - if(target != null) - { - Offline = true; - target.loadData(); - } - else - { - sender.sendMessage(ChatColor.RED + "Player not found!"); - return true; - } - } - } - if(!Offline) - { - sender.sendMessage(ChatColor.RED + "Player not found!"); - return true; - } - } - catch(Exception e) - { - sender.sendMessage("Error while retrieving offline player data!"); - e.printStackTrace(); - return true; - } - } - - //Permissions checks - if (!player.hasPermission("OpenInv.override") && target.hasPermission("OpenInv.exempt")) { + if (args.length > 0 && args[0].equalsIgnoreCase("?")) + { + OpenInv.ShowHelp((Player) sender); + return true; + } + + Player player = (Player) sender; + boolean offline = false; + + // History management + String history = openInvHistory.get(player); + + if (history == null || history == "") + { + history = player.getName(); + openInvHistory.put(player, history); + } + + // Target selecting + Player target; + + String name = ""; + + // Read from history if target is not named + if (args.length < 1) + { + if (history != null && history != "") + { + name = history; + } + else + { + sender.sendMessage(ChatColor.RED + "OpenInv history is empty!"); + return true; + } + } + else + { + name = args[0]; + } + + target = this.plugin.getServer().getPlayer(name); + + if (target == null) + { + // Offline inv here... + try + { + // See if the player has data files + + // Go through current world first, if not found then go through default world. + /* + * World worldFound = matchWorld(Bukkit.getWorlds(), player.getWorld().getName()); + * if (worldFound != null) + * { + * + * } + */ + + // Default player folder + File playerfolder = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "players"); + if (!playerfolder.exists()) + { + sender.sendMessage(ChatColor.RED + "Player " + name + " not found!"); + return true; + } + + String playername = matchUser(Arrays.asList(playerfolder.listFiles()), name); + if (playername == null) + { + sender.sendMessage(ChatColor.RED + "Player " + name + " not found!"); + return true; + } + + // Create an entity to load the player data + final MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + final EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), playername, new ItemInWorldManager(server.getWorldServer(0))); + target = (entity == null) ? null : (Player) entity.getBukkitEntity(); + if (target != null) + { + target.loadData(); + offline = true; + } + else + { + sender.sendMessage(ChatColor.RED + "Player " + name + " not found!"); + return true; + } + } + catch (Exception e) + { + sender.sendMessage("Error while retrieving offline player data!"); + e.printStackTrace(); + return true; + } + } + + // Permissions checks + if (!player.hasPermission("OpenInv.override") && target.hasPermission("OpenInv.exempt")) + { sender.sendMessage(ChatColor.RED + target.getDisplayName() + "'s inventory is protected!"); return true; } - - if((!player.hasPermission("OpenInv.crossworld") && !player.hasPermission("OpenInv.override")) && - target.getWorld() != player.getWorld()){ - sender.sendMessage(ChatColor.RED + target.getDisplayName() + " is not in your world!"); + + if ((!player.hasPermission("OpenInv.crossworld") && !player.hasPermission("OpenInv.override")) && target.getWorld() != player.getWorld()) + { + sender.sendMessage(ChatColor.RED + target.getDisplayName() + " is not in your world!"); return true; - } - - //Record the target - history = target.getName(); - openInvHistory.put(player, history); - - //Get the EntityPlayer handle from the sender - EntityPlayer entityplayer = ((CraftPlayer) player).getHandle(); - - //Get the EntityPlayer from the Target - EntityPlayer entitytarget = ((CraftPlayer) target).getHandle(); - - //Create the inventory - PlayerInventoryChest inv = new PlayerInventoryChest(entitytarget.inventory, entitytarget); - - //Save data into the inventory for tracking - inv.Opener = player; - inv.Target = target; - - //Saves offline openinv - if(Offline) - { - inv.Offline = true; - offlineInv.put(target, inv); - } - - //Open the inventory - entityplayer.openContainer(inv); - - return true; + } + + // Record the target + history = target.getName(); + openInvHistory.put(player, history); + + // Create the inventory + OpenInvPlayerInventory inv = OpenInv.inventories.get(target.getName().toLowerCase()); + if (inv == null) + { + inv = new OpenInvPlayerInventory((CraftPlayer) target, !offline); + + OpenInv.inventories.put(target.getName().toLowerCase(), inv); + } + + // Open the inventory + (((CraftPlayer) player).getHandle()).openContainer(inv); + + return true; + } + + /** + * @author Balor (aka Antoine Aflalo) + */ + private String matchUser(final Collection container, final String search) + { + String found = null; + if (search == null) + { + return found; + } + final String lowerSearch = search.toLowerCase(); + int delta = Integer.MAX_VALUE; + for (final File file : container) + { + final String filename = file.getName(); + final String str = filename.substring(0, filename.length() - 4); + if (!str.toLowerCase().startsWith(lowerSearch)) + { + continue; + } + final int curDelta = str.length() - lowerSearch.length(); + if (curDelta < delta) + { + found = str; + delta = curDelta; + } + if (curDelta == 0) + { + break; + } + + } + return found; } } diff --git a/src/lishid/openinv/commands/SearchInvPluginCommand.java b/src/lishid/openinv/commands/SearchInvPluginCommand.java index 63cc5f8..4bee2a8 100644 --- a/src/lishid/openinv/commands/SearchInvPluginCommand.java +++ b/src/lishid/openinv/commands/SearchInvPluginCommand.java @@ -25,55 +25,64 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class SearchInvPluginCommand implements CommandExecutor { +public class SearchInvPluginCommand implements CommandExecutor +{ private final OpenInv plugin; - public SearchInvPluginCommand(OpenInv plugin) { + + public SearchInvPluginCommand(OpenInv plugin) + { this.plugin = plugin; } - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - - if(sender instanceof Player) - { - if (!sender.hasPermission("OpenInv.search")) { + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) + { + if (sender instanceof Player) + { + if (!sender.hasPermission("OpenInv.search")) + { sender.sendMessage(ChatColor.RED + "You do not have permission to access player inventories"); return true; } - } - - - String PlayerList = ""; - + } + + String PlayerList = ""; + Material material = null; int count = 1; - - if (args.length >= 1) { + + if (args.length >= 1) + { String[] gData = null; gData = args[0].split(":"); material = Material.matchMaterial(gData[0]); } - if (args.length >= 2) { - try { + if (args.length >= 2) + { + try + { count = Integer.parseInt(args[1]); - } catch (NumberFormatException ex) { + } + catch (NumberFormatException ex) + { sender.sendMessage(ChatColor.RED + "'" + args[1] + "' is not a number!"); return false; } } - - if (material == null) { + + if (material == null) + { sender.sendMessage(ChatColor.RED + "Unknown item"); return false; } - - for(Player templayer : plugin.getServer().getOnlinePlayers()) - { - if(templayer.getInventory().contains(material, count)) - { - PlayerList += templayer.getName() + " "; - } - } - + + for (Player templayer : plugin.getServer().getOnlinePlayers()) + { + if (templayer.getInventory().contains(material, count)) + { + PlayerList += templayer.getName() + " "; + } + } + sender.sendMessage("Players with the item " + material.toString() + ": " + PlayerList); return true; } diff --git a/src/lishid/openinv/commands/SilentChestPluginCommand.java b/src/lishid/openinv/commands/SilentChestPluginCommand.java index 71a25e7..62c7f3b 100644 --- a/src/lishid/openinv/commands/SilentChestPluginCommand.java +++ b/src/lishid/openinv/commands/SilentChestPluginCommand.java @@ -24,36 +24,40 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class SilentChestPluginCommand implements CommandExecutor { - public SilentChestPluginCommand(OpenInv plugin) { - +public class SilentChestPluginCommand implements CommandExecutor +{ + public SilentChestPluginCommand(OpenInv plugin) + { + } - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) - { + 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 (!sender.hasPermission("OpenInv.silent")) { + return true; + } + if (!sender.hasPermission("OpenInv.silent")) + { sender.sendMessage(ChatColor.RED + "You do not have permission to use silent chest."); return true; } - - if(args.length > 0) - { - if(args[0].equalsIgnoreCase("check")) - { - if(OpenInv.GetPlayerSilentChestStatus(sender.getName())) - sender.sendMessage("SilentChest is ON."); - else - sender.sendMessage("SilentChest is OFF."); - } - } - - OpenInv.SetPlayerSilentChestStatus(sender.getName(), !OpenInv.GetPlayerSilentChestStatus(sender.getName())); - sender.sendMessage("SilentChest is now " + (OpenInv.GetPlayerSilentChestStatus(sender.getName())?"On":"Off") + "."); - + + if (args.length > 0) + { + if (args[0].equalsIgnoreCase("check")) + { + if (OpenInv.GetPlayerSilentChestStatus(sender.getName())) + sender.sendMessage("SilentChest is ON."); + else + sender.sendMessage("SilentChest is OFF."); + } + } + + OpenInv.SetPlayerSilentChestStatus(sender.getName(), !OpenInv.GetPlayerSilentChestStatus(sender.getName())); + sender.sendMessage("SilentChest is now " + (OpenInv.GetPlayerSilentChestStatus(sender.getName()) ? "On" : "Off") + "."); + return true; } } diff --git a/src/lishid/openinv/commands/ToggleOpenInvPluginCommand.java b/src/lishid/openinv/commands/ToggleOpenInvPluginCommand.java index 302b1c3..2eb1baf 100644 --- a/src/lishid/openinv/commands/ToggleOpenInvPluginCommand.java +++ b/src/lishid/openinv/commands/ToggleOpenInvPluginCommand.java @@ -25,40 +25,43 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -public class ToggleOpenInvPluginCommand implements CommandExecutor { +public class ToggleOpenInvPluginCommand implements CommandExecutor +{ - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) - { + 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 (!sender.hasPermission("OpenInv.openinv")) { + return true; + } + if (!sender.hasPermission("OpenInv.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")) - { - if(OpenInv.GetPlayerItemOpenInvStatus(player.getName())) - player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is ON."); - else - player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is OFF."); - } - } - if(OpenInv.GetPlayerItemOpenInvStatus(player.getName())) - { - OpenInv.SetPlayerItemOpenInvStatus(player.getName(), false); - player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is OFF."); - } - else - { - OpenInv.SetPlayerItemOpenInvStatus(player.getName(), true); - player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is ON."); - } - return true; + + Player player = (Player) sender; + if (args.length > 0) + { + if (args[0].equalsIgnoreCase("check")) + { + if (OpenInv.GetPlayerItemOpenInvStatus(player.getName())) + player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is ON."); + else + player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is OFF."); + } + } + if (OpenInv.GetPlayerItemOpenInvStatus(player.getName())) + { + OpenInv.SetPlayerItemOpenInvStatus(player.getName(), false); + player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is OFF."); + } + else + { + OpenInv.SetPlayerItemOpenInvStatus(player.getName(), true); + player.sendMessage("OpenInv with " + Material.getMaterial(OpenInv.GetItemOpenInvItem()).toString() + " is ON."); + } + return true; } } diff --git a/src/lishid/openinv/utils/Metrics.java b/src/lishid/openinv/utils/Metrics.java index 364cc43..ec915b1 100644 --- a/src/lishid/openinv/utils/Metrics.java +++ b/src/lishid/openinv/utils/Metrics.java @@ -30,6 +30,7 @@ package lishid.openinv.utils; import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; @@ -49,6 +50,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import java.util.UUID; +import java.util.logging.Level; /** *

@@ -63,430 +65,631 @@ import java.util.UUID; * void start();
* */ -public class Metrics { - +public class Metrics +{ + /** * The current revision number */ private final static int REVISION = 5; - + /** * The base url of the metrics domain */ - private static final String BASE_URL = "http://metrics.griefcraft.com"; - + private static final String BASE_URL = "http://mcstats.org"; + /** * The url used to report a server's status */ private static final String REPORT_URL = "/report/%s"; - + /** * The file where guid and opt out is stored in */ private static final String CONFIG_FILE = "plugins/PluginMetrics/config.yml"; - + /** * The separator to use for custom data. This MUST NOT change unless you are hosting your own * version of metrics and want to change it. */ private static final String CUSTOM_DATA_SEPARATOR = "~~"; - + /** * Interval of time to ping (in minutes) */ - private final static int PING_INTERVAL = 10; - + private static final int PING_INTERVAL = 10; + /** * The plugin this metrics submits for */ private final Plugin plugin; - + /** * All of the custom graphs to submit to metrics */ private final Set graphs = Collections.synchronizedSet(new HashSet()); - + /** * The default graph, used for addCustomData when you don't want a specific graph */ private final Graph defaultGraph = new Graph("Default"); - + /** * The plugin configuration file */ private final YamlConfiguration configuration; - + + /** + * The plugin configuration file + */ + private final File configurationFile; + /** * Unique server id */ private final String guid; - - public Metrics(Plugin plugin) throws IOException { - if (plugin == null) { + + /** + * Lock for synchronization + */ + private final Object optOutLock = new Object(); + + /** + * Id of the scheduled task + */ + private volatile int taskId = -1; + + public Metrics(final Plugin plugin) throws IOException + { + if (plugin == null) + { throw new IllegalArgumentException("Plugin cannot be null"); } - + this.plugin = plugin; - + // load the config - File file = new File(CONFIG_FILE); - configuration = YamlConfiguration.loadConfiguration(file); - + configurationFile = new File(CONFIG_FILE); + configuration = YamlConfiguration.loadConfiguration(configurationFile); + // add some defaults configuration.addDefault("opt-out", false); configuration.addDefault("guid", UUID.randomUUID().toString()); - + // Do we need to create the file? - if (configuration.get("guid", null) == null) { - configuration.options().header("http://metrics.griefcraft.com").copyDefaults(true); - configuration.save(file); + if (configuration.get("guid", null) == null) + { + configuration.options().header("http://mcstats.org").copyDefaults(true); + configuration.save(configurationFile); } - + // Load the guid then guid = configuration.getString("guid"); } - + /** * Construct and create a Graph that can be used to separate specific plotters to their own graphs * on the metrics website. Plotters can be added to the graph object returned. - * + * * @param name * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given */ - public Graph createGraph(String name) { - if (name == null) { + public Graph createGraph(final String name) + { + if (name == null) + { throw new IllegalArgumentException("Graph name cannot be null"); } - + // Construct the graph object - Graph graph = new Graph(name); - + final Graph graph = new Graph(name); + // Now we can add our graph graphs.add(graph); - + // and return back return graph; } - + + /** + * Add a Graph object to Metrics that represents data for the plugin that should be sent to the backend + * + * @param graph + */ + public void addGraph(final Graph graph) + { + if (graph == null) + { + throw new IllegalArgumentException("Graph cannot be null"); + } + + graphs.add(graph); + } + /** * Adds a custom data plotter to the default graph - * + * * @param plotter */ - public void addCustomData(Plotter plotter) { - if (plotter == null) { + public void addCustomData(final Plotter plotter) + { + if (plotter == null) + { throw new IllegalArgumentException("Plotter cannot be null"); } - + // Add the plotter to the graph o/ defaultGraph.addPlotter(plotter); - + // Ensure the default graph is included in the submitted graphs graphs.add(defaultGraph); } - + /** * Start measuring statistics. This will immediately create an async repeating task as the plugin and send * the initial data to the metrics backend, and then after that it will post in increments of * PING_INTERVAL * 1200 ticks. + * + * @return True if statistics measuring is running, otherwise false. */ - public void start() { - // Did we opt out? - if (configuration.getBoolean("opt-out", false)) { - return; - } - - // Begin hitting the server with glorious data - plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() { - private boolean firstPost = true; - - public void run() { - try { - // We use the inverse of firstPost because if it is the first time we are posting, - // it is not a interval ping, so it evaluates to FALSE - // Each time thereafter it will evaluate to TRUE, i.e PING! - postPlugin(!firstPost); - - // After the first post we set firstPost to false - // Each post thereafter will be a ping - firstPost = false; - } catch (Exception e) { - System.err.println("[Metrics] " + e.getMessage()); - } + public boolean start() + { + synchronized (optOutLock) + { + // Did we opt out? + if (isOptOut()) + { + return false; } - }, 0, PING_INTERVAL * 1200); + + // Is metrics already running? + if (taskId >= 0) + { + return true; + } + + // Begin hitting the server with glorious data + taskId = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() + { + + private boolean firstPost = true; + + public void run() + { + try + { + // This has to be synchronized or it can collide with the disable method. + synchronized (optOutLock) + { + // Disable Task, if it is running and the server owner decided to opt-out + if (isOptOut() && taskId > 0) + { + plugin.getServer().getScheduler().cancelTask(taskId); + taskId = -1; + // Tell all plotters to stop gathering information. + for (Graph graph : graphs) + { + graph.onOptOut(); + } + } + } + + // We use the inverse of firstPost because if it is the first time we are posting, + // it is not a interval ping, so it evaluates to FALSE + // Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(!firstPost); + + // After the first post we set firstPost to false + // Each post thereafter will be a ping + firstPost = false; + } + catch (IOException e) + { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); + } + } + }, 0, PING_INTERVAL * 1200); + + return true; + } } - + + /** + * Has the server owner denied plugin metrics? + * + * @return + */ + public boolean isOptOut() + { + synchronized (optOutLock) + { + try + { + // Reload the metrics file + configuration.load(CONFIG_FILE); + } + catch (IOException ex) + { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + return true; + } + catch (InvalidConfigurationException ex) + { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + return true; + } + return configuration.getBoolean("opt-out", false); + } + } + + /** + * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. + * + * @throws IOException + */ + public void enable() throws IOException + { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) + { + // Check if the server owner has already set opt-out, if not, set it. + if (isOptOut()) + { + configuration.set("opt-out", false); + configuration.save(configurationFile); + } + + // Enable Task, if it is not running + if (taskId < 0) + { + start(); + } + } + } + + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + * @throws IOException + */ + public void disable() throws IOException + { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) + { + // Check if the server owner has already set opt-out, if not, set it. + if (!isOptOut()) + { + configuration.set("opt-out", true); + configuration.save(configurationFile); + } + + // Disable Task, if it is running + if (taskId > 0) + { + this.plugin.getServer().getScheduler().cancelTask(taskId); + taskId = -1; + } + } + } + /** * Generic method that posts a plugin to the metrics website */ - private void postPlugin(boolean isPing) throws IOException { + private void postPlugin(final boolean isPing) throws IOException + { // The plugin's description file containg all of the plugin data such as name, version, author, etc - PluginDescriptionFile description = plugin.getDescription(); - + final PluginDescriptionFile description = plugin.getDescription(); + // Construct the post data - String data = encode("guid") + '=' + encode(guid) - + encodeDataPair("version", description.getVersion()) - + encodeDataPair("server", Bukkit.getVersion()) - + encodeDataPair("players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length)) - + encodeDataPair("revision", String.valueOf(REVISION)); - + final StringBuilder data = new StringBuilder(); + data.append(encode("guid")).append('=').append(encode(guid)); + encodeDataPair(data, "version", description.getVersion()); + encodeDataPair(data, "server", Bukkit.getVersion()); + encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length)); + encodeDataPair(data, "revision", String.valueOf(REVISION)); + // If we're pinging, append it - if (isPing) { - data += encodeDataPair("ping", "true"); + if (isPing) + { + encodeDataPair(data, "ping", "true"); } - + // Acquire a lock on the graphs, which lets us make the assumption we also lock everything // inside of the graph (e.g plotters) - synchronized (graphs) { - Iterator iter = graphs.iterator(); - - while (iter.hasNext()) { - Graph graph = iter.next(); - - // Because we have a lock on the graphs set already, it is reasonable to assume - // that our lock transcends down to the individual plotters in the graphs also. - // Because our methods are private, no one but us can reasonably access this list - // without reflection so this is a safe assumption without adding more code. - for (Plotter plotter : graph.getPlotters()) { + synchronized (graphs) + { + final Iterator iter = graphs.iterator(); + + while (iter.hasNext()) + { + final Graph graph = iter.next(); + + for (Plotter plotter : graph.getPlotters()) + { // The key name to send to the metrics server // The format is C-GRAPHNAME-PLOTTERNAME where separator - is defined at the top // Legacy (R4) submitters use the format Custom%s, or CustomPLOTTERNAME - String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName()); - + final String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName()); + // The value to send, which for the foreseeable future is just the string // value of plotter.getValue() - String value = Integer.toString(plotter.getValue()); - + final String value = Integer.toString(plotter.getValue()); + // Add it to the http post data :) - data += encodeDataPair(key, value); + encodeDataPair(data, key, value); } } } - + // Create the url - URL url = new URL(BASE_URL + String.format(REPORT_URL, description.getName())); - + URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(plugin.getDescription().getName()))); + // Connect to the website URLConnection connection; - + // Mineshafter creates a socks proxy, so we can safely bypass it // It does not reroute POST requests so we need to go around it - if (isMineshafterPresent()) { + if (isMineshafterPresent()) + { connection = url.openConnection(Proxy.NO_PROXY); - } else { + } + else + { connection = url.openConnection(); } - + connection.setDoOutput(true); - + // Write the data - OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); - writer.write(data); + final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); + writer.write(data.toString()); writer.flush(); - + // Now read the response - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String response = reader.readLine(); - + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + final String response = reader.readLine(); + // close resources writer.close(); reader.close(); - - if (response.startsWith("ERR")) { - throw new IOException(response); //Throw the exception - } else { + + if (response == null || response.startsWith("ERR")) + { + throw new IOException(response); // Throw the exception + } + else + { // Is this the first update this hour? - if (response.contains("OK This is your first update this hour")) { - synchronized (graphs) { - Iterator iter = graphs.iterator(); - - while (iter.hasNext()) { - Graph graph = iter.next(); - - for (Plotter plotter : graph.getPlotters()) { + if (response.contains("OK This is your first update this hour")) + { + synchronized (graphs) + { + final Iterator iter = graphs.iterator(); + + while (iter.hasNext()) + { + final Graph graph = iter.next(); + + for (Plotter plotter : graph.getPlotters()) + { plotter.reset(); } } } } } - //if (response.startsWith("OK")) - We should get "OK" followed by an optional description if everything goes right } - + /** * Check if mineshafter is present. If it is, we need to bypass it to send POST requests - * + * * @return */ - private boolean isMineshafterPresent() { - try { + private boolean isMineshafterPresent() + { + try + { Class.forName("mineshafter.MineServer"); return true; - } catch (Exception e) { + } + catch (Exception e) + { return false; } } - + /** - *

Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first - * key/value pair MUST be included manually, e.g:

+ *

+ * Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first key/value pair MUST be included manually, e.g: + *

* - * String httpData = encode("guid") + '=' + encode("1234") + encodeDataPair("authors") + ".."; + * StringBuffer data = new StringBuffer(); + * data.append(encode("guid")).append('=').append(encode(guid)); + * encodeDataPair(data, "version", description.getVersion()); * - * + * + * @param buffer * @param key * @param value * @return */ - private static String encodeDataPair(String key, String value) throws UnsupportedEncodingException { - return '&' + encode(key) + '=' + encode(value); + private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException + { + buffer.append('&').append(encode(key)).append('=').append(encode(value)); } - + /** * Encode text as UTF-8 - * + * * @param text * @return */ - private static String encode(String text) throws UnsupportedEncodingException { + private static String encode(final String text) throws UnsupportedEncodingException + { return URLEncoder.encode(text, "UTF-8"); } - + /** * Represents a custom graph on the website */ - public static class Graph { - + public static class Graph + { + /** * The graph's name, alphanumeric and spaces only :) * If it does not comply to the above when submitted, it is rejected */ private final String name; - + /** * The set of plotters that are contained within this graph */ private final Set plotters = new LinkedHashSet(); - - private Graph(String name) { + + private Graph(final String name) + { this.name = name; } - + /** * Gets the graph's name - * + * * @return */ - public String getName() { + public String getName() + { return name; } - + /** * Add a plotter to the graph, which will be used to plot entries - * + * * @param plotter */ - public void addPlotter(Plotter plotter) { + public void addPlotter(final Plotter plotter) + { plotters.add(plotter); } - + /** * Remove a plotter from the graph - * + * * @param plotter */ - public void removePlotter(Plotter plotter) { + public void removePlotter(final Plotter plotter) + { plotters.remove(plotter); } - + /** * Gets an unmodifiable set of the plotter objects in the graph - * + * * @return */ - public Set getPlotters() { + public Set getPlotters() + { return Collections.unmodifiableSet(plotters); } - + @Override - public int hashCode() { + public int hashCode() + { return name.hashCode(); } - + @Override - public boolean equals(Object object) { - if (!(object instanceof Graph)) { + public boolean equals(final Object object) + { + if (!(object instanceof Graph)) + { return false; } - - Graph graph = (Graph) object; + + final Graph graph = (Graph) object; return graph.name.equals(name); } - + + /** + * Called when the server owner decides to opt-out of Metrics while the server is running. + */ + protected void onOptOut() + { + } + } - + /** * Interface used to collect custom data for a plugin */ - public static abstract class Plotter { - + public static abstract class Plotter + { + /** * The plot's name */ private final String name; - + /** * Construct a plotter with the default plot name */ - public Plotter() { + public Plotter() + { this("Default"); } - + /** * Construct a plotter with a specific plot name - * + * * @param name */ - public Plotter(String name) { + public Plotter(final String name) + { this.name = name; } - + /** * Get the current value for the plotted point - * + * * @return */ public abstract int getValue(); - + /** * Get the column name for the plotted point - * + * * @return the plotted point's column name */ - public String getColumnName() { + public String getColumnName() + { return name; } - + /** * Called after the website graphs have been updated */ - public void reset() { + public void reset() + { } - + @Override - public int hashCode() { - return getColumnName().hashCode() + getValue(); + public int hashCode() + { + return getColumnName().hashCode(); } - + @Override - public boolean equals(Object object) { - if (!(object instanceof Plotter)) { + public boolean equals(final Object object) + { + if (!(object instanceof Plotter)) + { return false; } - - Plotter plotter = (Plotter) object; + + final Plotter plotter = (Plotter) object; return plotter.name.equals(name) && plotter.getValue() == getValue(); } + } + } \ No newline at end of file diff --git a/src/lishid/openinv/utils/PlayerInventoryChest.java b/src/lishid/openinv/utils/OpenInvPlayerInventory.java similarity index 59% rename from src/lishid/openinv/utils/PlayerInventoryChest.java rename to src/lishid/openinv/utils/OpenInvPlayerInventory.java index 7eb1944..eaefc0d 100644 --- a/src/lishid/openinv/utils/PlayerInventoryChest.java +++ b/src/lishid/openinv/utils/OpenInvPlayerInventory.java @@ -16,39 +16,60 @@ package lishid.openinv.utils; -import java.util.ArrayList; -import java.util.List; +import lishid.openinv.OpenInv; import org.bukkit.craftbukkit.entity.CraftHumanEntity; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; +import org.bukkit.craftbukkit.entity.CraftPlayer; -import lishid.openinv.commands.OpenInvPluginCommand; import net.minecraft.server.EntityHuman; -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.IInventory; import net.minecraft.server.ItemStack; import net.minecraft.server.PlayerInventory; -public class PlayerInventoryChest implements IInventory +public class OpenInvPlayerInventory extends PlayerInventory { - public boolean Offline = false; - public Player Opener; - EntityPlayer player; - public Player Target; - private ItemStack[] items = new ItemStack[36]; - private ItemStack[] armor = new ItemStack[4]; + CraftPlayer owner; + public boolean playerOnline = false; private ItemStack[] extra = new ItemStack[5]; - private int maxStack = MAX_STACK; - - public PlayerInventoryChest(PlayerInventory inventory, EntityPlayer entityplayer) + + public OpenInvPlayerInventory(CraftPlayer p, boolean online) { - player = entityplayer; - this.items = inventory.items; - this.armor = inventory.armor; + super(p.getHandle()); + this.owner = p; + this.items = player.inventory.items; + this.armor = player.inventory.armor; } - + + public void onClose(CraftHumanEntity who) + { + super.onClose(who); + this.InventoryRemovalCheck(); + } + + public void InventoryRemovalCheck() + { + if (transaction.isEmpty() && !playerOnline) + { + owner.saveData(); + OpenInv.inventories.remove(owner.getName().toLowerCase()); + } + } + + public void PlayerGoOnline(CraftPlayer p) + { + if(!playerOnline) + { + p.getHandle().inventory.items = this.items; + p.getHandle().inventory.armor = this.armor; + p.saveData(); + playerOnline = true; + } + } + + public void PlayerGoOffline() + { + playerOnline = false; + } + public ItemStack[] getContents() { ItemStack[] C = new ItemStack[getSize()]; @@ -56,16 +77,16 @@ public class PlayerInventoryChest implements IInventory System.arraycopy(items, 0, C, items.length, armor.length); return C; } - + public int getSize() { - return 45; + return super.getSize() + 5; } - + public ItemStack getItem(int i) { ItemStack[] is = this.items; - + if (i >= is.length) { i -= is.length; @@ -75,24 +96,24 @@ public class PlayerInventoryChest implements IInventory { i = getReversedItemSlotNum(i); } - + if (i >= is.length) { i -= is.length; is = this.extra; } - else if(is == this.armor) + else if (is == this.armor) { i = getReversedArmorSlotNum(i); } - + return is[i]; } - + public ItemStack splitStack(int i, int j) { ItemStack[] is = this.items; - + if (i >= is.length) { i -= is.length; @@ -102,21 +123,21 @@ public class PlayerInventoryChest implements IInventory { i = getReversedItemSlotNum(i); } - + if (i >= is.length) { i -= is.length; is = this.extra; } - else if(is == this.armor) + else if (is == this.armor) { i = getReversedArmorSlotNum(i); } - + if (is[i] != null) { ItemStack itemstack; - + if (is[i].count <= j) { itemstack = is[i]; @@ -130,7 +151,7 @@ public class PlayerInventoryChest implements IInventory { is[i] = null; } - + return itemstack; } } @@ -139,10 +160,11 @@ public class PlayerInventoryChest implements IInventory return null; } } - - public ItemStack splitWithoutUpdate(int i) { + + public ItemStack splitWithoutUpdate(int i) + { ItemStack[] is = this.items; - + if (i >= is.length) { i -= is.length; @@ -152,31 +174,34 @@ public class PlayerInventoryChest implements IInventory { i = getReversedItemSlotNum(i); } - + if (i >= is.length) { i -= is.length; is = this.extra; } - else if(is == this.armor) + else if (is == this.armor) { i = getReversedArmorSlotNum(i); } - if (is[i] != null) { + if (is[i] != null) + { ItemStack itemstack = is[i]; - + is[i] = null; return itemstack; - } else { + } + else + { return null; } } - + public void setItem(int i, ItemStack itemstack) { ItemStack[] is = this.items; - + if (i >= is.length) { i -= is.length; @@ -186,108 +211,65 @@ public class PlayerInventoryChest implements IInventory { i = getReversedItemSlotNum(i); } - + if (i >= is.length) { i -= is.length; is = this.extra; } - else if(is == this.armor) + else if (is == this.armor) { i = getReversedArmorSlotNum(i); } /* + * + * //Effects + * if(is == this.extra) + * { + * if(i == 0) + * { + * itemstack.setData(0); + * } + * } + */ - //Effects - if(is == this.extra) - { - if(i == 0) - { - itemstack.setData(0); - } - }*/ - is[i] = itemstack; } - + private int getReversedItemSlotNum(int i) { - if (i >= 27) return i - 27; - else return i + 9; + if (i >= 27) + return i - 27; + else + return i + 9; } - + private int getReversedArmorSlotNum(int i) { - if (i == 0) return 3; - if (i == 1) return 2; - if (i == 2) return 1; - if (i == 3) return 0; - else return i; + if (i == 0) + return 3; + if (i == 1) + return 2; + if (i == 2) + return 1; + if (i == 3) + return 0; + else + return i; } - + public String getName() { - if (player.name.length() > 16) return player.name.substring(0, 16); + if (player.name.length() > 16) + { + return player.name.substring(0, 16); + } return player.name; } - - public int getMaxStackSize() - { - return maxStack; - } - + public boolean a(EntityHuman entityhuman) { return true; } - - public void f() - { - - } - - public void g() - { - try - { - PlayerInventoryChest inv = OpenInvPluginCommand.offlineInv.get(this.Target); - if (inv != null) - { - this.Target.saveData(); - OpenInvPluginCommand.offlineInv.remove(this.Target); - } - } - catch (Exception e) - {} - } - - public void update() - { - - } - - public List transaction = new ArrayList(); - - public void onOpen(CraftHumanEntity who) { - transaction.add(who); - } - - public void onClose(CraftHumanEntity who) { - transaction.remove(who); - } - - public List getViewers() { - return transaction; - } - - @Override - public InventoryHolder getOwner() { - return null; - } - - @Override - public void setMaxStackSize(int size) { - maxStack = size; - } } \ No newline at end of file diff --git a/src/lishid/openinv/utils/SilentContainerChest.java b/src/lishid/openinv/utils/SilentContainerChest.java index 6136144..8072a0f 100644 --- a/src/lishid/openinv/utils/SilentContainerChest.java +++ b/src/lishid/openinv/utils/SilentContainerChest.java @@ -20,17 +20,23 @@ import net.minecraft.server.ContainerChest; import net.minecraft.server.EntityHuman; import net.minecraft.server.IInventory; -public class SilentContainerChest extends ContainerChest { - public IInventory inv; - public SilentContainerChest(IInventory i1, IInventory i2) { - super(i1, i2); - inv = i2; - inv.g();//close signal +public class SilentContainerChest extends ContainerChest +{ + public IInventory inv; + + public SilentContainerChest(IInventory i1, IInventory i2) + { + super(i1, i2); + inv = i2; + // close signal + inv.g(); } @Override - public void a(EntityHuman paramEntityHuman) { + public void a(EntityHuman paramEntityHuman) + { super.a(paramEntityHuman); - inv.f();//open signal + // open signal + inv.f(); } } \ No newline at end of file diff --git a/src/plugin.yml b/src/plugin.yml index 5f1014b..3fc252d 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,6 +1,6 @@ name: OpenInv main: lishid.openinv.OpenInv -version: 1.8.4 +version: 1.8.5 author: lishid website: http://forums.bukkit.org/threads/15379/ description: >