package dk.thoerup.bukkit.hoeruputils.chests; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.Chest; import org.bukkit.block.DoubleChest; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBurnEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import dk.thoerup.bukkit.hoeruputils.HoerupUtilsPlugin; import dk.thoerup.bukkit.hoeruputils.Util; public class AdvancedChest implements Listener, CommandExecutor{ class ItemCount extends TreeMap { private static final long serialVersionUID = 1L; }; HashMap contentMap = new HashMap(); HashMap chestMap = new HashMap(); HoerupUtilsPlugin plugin; Server server; public AdvancedChest(HoerupUtilsPlugin plugin, Runnable r) { this.plugin = plugin; server = plugin.getServer(); try { loadChests(); } catch (Exception e) { e.printStackTrace(); //r.run(); loadChests(); } } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (! (sender instanceof Player) ) { sender.sendMessage("this is not a console command!"); return true; } Player player = (Player) sender; if (args.length == 0) { player.sendMessage("Usage:"); player.sendMessage("/chest (status|lock|snitch|remove|addplayer|removeplayer|setowner|comment) [player]"); return true; } Block b = player.getTargetBlock( (Set)null, 30); Material mat = b.getType(); if (mat != Material.CHEST && mat != Material.HOPPER) { player.sendMessage("[Chest] Please look at the chest/hopper you want to protect"); return true; } Location loc = b.getLocation(); Location loc2 = null; if ( mat == Material.HOPPER) { //dont find neighbours for Hoppers loc2 = getNeighborChest(loc); } ChestBean chest = chestMap.get(loc); String cmd = args[0].toLowerCase(); if (cmd.equals("status")) { if (chest != null) { String mode = ""; switch (chest.getChestType()) { case ChestBean.LOCKED: mode = "locked"; break; case ChestBean.SNITCHING: mode = "snitching"; break; default: mode = "unknown ??"; } player.sendMessage(ChatColor.GREEN + "Chest is a " + mode + " chest owned by " + chest.getOwner()); player.sendMessage(ChatColor.GREEN + "Allowed players: " + chest.getModifyPlayers() ); player.sendMessage(ChatColor.GREEN + "Comment: " + chest.getComment() ); } else { player.sendMessage(ChatColor.GREEN + "The chest is not protected"); } return true; } if (cmd.equals("lock") || cmd.equals("snitch")) { if (chest == null) { chest = createChest(player.getName(), "", loc); if (loc2 != null) { chest.setDoublechest(true); } String modeStr = ""; if (cmd.equals("lock")) { chest.setChestType( ChestBean.LOCKED); modeStr = "locked"; } else { chest.setChestType( ChestBean.SNITCHING); modeStr = "snitching"; } chest.setModifyPlayers(""); chest.setComment(""); addChest(loc, chest); player.sendMessage("Chest is now " + modeStr); } else { server.getLogger().info( player.getName() + " tried to protect a chest owned by " + chest.getOwner() ); player.sendMessage("This chest is already protected"); } return true; } if (cmd.equals("remove")) { if (chest == null) { player.sendMessage("This chest is not protected"); return true; } if ( chest.getOwner().equals( player.getName() ) || player.isOp() ) { //do nothing } else { player.sendMessage("You can not remove lock from a chest you don't own"); server.getLogger().info( player.getName() + " tried to remove protection froma chest owned by " + chest.getOwner() ); return true; } player.sendMessage("[LockedChest] Removing protection from chest"); removeChest(loc); return true; } if (cmd.equals("setowner")) { if (chest == null) { player.sendMessage("This chest is not protected"); return true; } if ( chest.getOwner().equals( player.getName() ) || player.isOp() ) { //do nothing } else { player.sendMessage("You can not set new owner of a chest you dont own"); server.getLogger().info( player.getName() + " tried to set owner on a chest owned by " + chest.getOwner() ); return true; } if (args.length != 2) { player.sendMessage("You need to specify which player should own this chest"); return true; } @SuppressWarnings("deprecation")//user by name is our only option here OfflinePlayer p2 = server.getOfflinePlayer(args[1]); if ( p2.hasPlayedBefore() == false && p2.isOnline() == false) { player.sendMessage("Unknown user: " + args[1] ); return true; } chest.setOwner( p2.getName() ); plugin.getDatabase().save( chest ); player.sendMessage("ok"); return true; } if (cmd.equals("addplayer") || cmd.equals("removeplayer")) { if (chest == null) { player.sendMessage("This chest is not protected"); return true; } if (! chest.getOwner().equals( player.getName() ) ) { player.sendMessage("You can not add/remove players from a chest you don't own"); server.getLogger().info( player.getName() + " tried to add/remove player on a chest owned by " + chest.getOwner() ); return true; } if (args.length != 2) { player.sendMessage("You need to specify which player to add or remove"); return true; } @SuppressWarnings("deprecation")//user by name is our only option here OfflinePlayer p2 = server.getOfflinePlayer(args[1]); if ( p2.hasPlayedBefore() == false && p2.isOnline() == false) { player.sendMessage("Unknown user: " + args[1] ); return true; } Set players = Util.stringToSet( chest.getModifyPlayers() ); if (cmd.equals("addplayer")) { players.add(p2.getName()); } else { players.remove(p2.getName()); } chest.setModifyPlayers( Util.setToString(players) ); plugin.getDatabase().save( chest ); player.sendMessage("ok"); return true; } if (cmd.equals("comment")) { if (chest == null) { player.sendMessage("This chest is not protected"); return true; } if (! chest.getOwner().equals( player.getName() ) ) { player.sendMessage("You can not comment a chest you don't own"); server.getLogger().info( player.getName() + " tried to comment on a chest owned by " + chest.getOwner() ); return true; } StringBuilder sb = new StringBuilder(); for (int i=1; i chestlist = plugin.getDatabase().find( ChestBean.class).findList(); for (ChestBean chest : chestlist) { Location loc = getChestLocation(server, chest); chestMap.put(loc, chest); if (chest.isDoublechest()) { Location loc2 = getNeighborChest(loc); chestMap.put(loc2, chest); } } return chestlist.size(); } void reloadChests() { chestMap.clear(); loadChestsWorker(); } void loadChests() { int count = loadChestsWorker(); server.getLogger().info("[AdvancedChest] loaded " + count + " chests"); } public ChestBean createChest(String owner, String description, Location loc) { ChestBean chest = new ChestBean(); chest.setOwner(owner); chest.setDescription(description); setChestLocation(chest, loc); return chest; } public void setChestLocation(ChestBean chest, Location loc) { chest.setWorld( loc.getWorld().getName() ); chest.setX( loc.getBlockX() ); chest.setY( loc.getBlockY() ); chest.setZ( loc.getBlockZ() ); } public Location getChestLocation(Server server, ChestBean chest) { World wrld = server.getWorld(chest.getWorld()); return new Location(wrld,chest.getX(),chest.getY(),chest.getZ()); } /* void saveChests() { }*/ Location getNeighborChest(Location loc) { World world = loc.getWorld(); Location target = new Location(world, loc.getX()+1, loc.getY(), loc.getZ() ); if (world.getBlockAt(target).getType() == Material.CHEST ) return target; target = new Location(world, loc.getX()-1, loc.getY(), loc.getZ() ); if (world.getBlockAt(target).getType() == Material.CHEST ) return target; target = new Location(world, loc.getX(), loc.getY(), loc.getZ() +1); if (world.getBlockAt(target).getType() == Material.CHEST ) return target; target = new Location(world, loc.getX(), loc.getY(), loc.getZ() -1); if (world.getBlockAt(target).getType() == Material.CHEST ) return target; return null; } Location getChestLocation(InventoryHolder holder) { Location loc; if ( holder instanceof Chest) { loc = ( (Chest)holder).getLocation(); } else { loc = ( (DoubleChest)holder).getLocation(); } loc.setX( loc.getBlockX() ); //round to integer, since double chests apparently are placed at pos + 0.5 loc.setZ( loc.getBlockZ() ); // -- // -- return loc; } @EventHandler public void onChestPlaced(BlockPlaceEvent event) { Block block = event.getBlock(); if (block.getType() != Material.CHEST) { return; } Location chestloc = getNeighborChest( block.getLocation() ); if (chestloc == null) return; ChestBean chest = chestMap.get(chestloc); if (chest == null)//the neighbor is not a locked chest return; chest.setDoublechest(true); addChest(chestloc, chest); event.getPlayer().sendMessage( "[AdvancedChest] Chest has been expanded" ); } @EventHandler public void onChestExplode(EntityExplodeEvent event) { for (Block b : event.blockList() ) { ChestBean chest = chestMap.get( b.getLocation() ); if (chest != null) { server.getLogger().info( "[AdvancedChest] Prevented an explosion from destroying chest owned by " + chest.getOwner() + chest.getCommentString() ); event.setCancelled( true ); return; } } } @EventHandler public void onChestBurn(BlockBurnEvent event) { ChestBean chest = chestMap.get( event.getBlock().getLocation() ); if (chest != null) { server.getLogger().info( "[AdvancedChest] prevented a fire from destrying chest owned by " + chest.getOwner() + chest.getCommentString() ); event.setCancelled( true); } } // prevent a user from opening a chest @EventHandler public void onChestInteract(PlayerInteractEvent event) { if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { Block b = event.getClickedBlock(); if (b.getType() == Material.CHEST) { Location loc = b.getLocation(); ChestBean chest = chestMap.get( loc ); if (chest == null) { return; //chest not surveyed by this plugin } if (chest.getChestType() != ChestBean.LOCKED ) { return; //this is not a locked chests } Player player = (Player) event.getPlayer(); if (player.getName().equals(chest.getOwner() )) { return; //chest is opened by it's owner } Set players = chest.getModifyPlayersSet() ; if ( players.contains(player.getName()) ) { return; //this player is on the whitelist so he may open } server.getLogger().info( "[AdvancedChest] " + event.getPlayer().getName() + " tried opening a chest owned by " + chest.getOwner() + chest.getCommentString() ); player.sendMessage( ChatColor.BLUE + "Sorry but this chest is locked !"); event.setCancelled(true); } } } @EventHandler public void onChestOpen(InventoryOpenEvent event) { if (! (event.getPlayer() instanceof Player)) { return; } InventoryHolder holder = event.getInventory().getHolder(); if (holder instanceof Chest || holder instanceof DoubleChest) { Location loc = getChestLocation(holder); ChestBean chest = chestMap.get( loc ); if (chest == null) { return; //chest not surveyed by this plugin } if (chest.getChestType() != ChestBean.SNITCHING) { return; // not a snitching chest } Player player = (Player) event.getPlayer(); if (player.getName().equals(chest.getOwner() )) { return; //chest is owned by it's own player } Set players = chest.getModifyPlayersSet(); if ( players.contains(player.getName()) ) { return; //this player is on the whitelist so he may open } server.getLogger().info( "[AdvancedChest] " + event.getPlayer().getName() + " opened a snitching chest owned by " + chest.getOwner() + chest.getCommentString() ); ItemCount contents = countItems( event.getInventory().getContents() ); contentMap.put(player.getName(), contents ); } } @EventHandler public void onChestClose(InventoryCloseEvent event) { if (! (event.getPlayer() instanceof Player)) { return; } InventoryHolder holder = event.getInventory().getHolder(); if (holder instanceof Chest || holder instanceof DoubleChest) { Location loc = getChestLocation(holder); ChestBean chest = chestMap.get(loc); if (chest == null) { //chest was not a snitching chest return; } if (chest.getChestType() != ChestBean.SNITCHING) { return; // not a snitching chest } OfflinePlayer owner = server.getOfflinePlayer( chest.getOwner() ); Player player = (Player) event.getPlayer(); ItemCount savedContent = contentMap.get( player.getName() ); if (savedContent == null) { return; } contentMap.remove( player.getName() ); ItemCount content = countItems( event.getInventory().getContents() ); Set combinedKeyset = new TreeSet(); combinedKeyset.addAll( savedContent.keySet() ); combinedKeyset.addAll( content.keySet() ); for (Material material : combinedKeyset ) { Integer savedcount = savedContent.get(material); Integer count = content.get(material); if (savedcount == null) savedcount = 0; if (count == null) count = 0; int diff = Math.abs( savedcount - count); if (diff > 0) { String msg = null; if (count > savedcount) { msg = player.getName() + " added " + diff + " units of " + material + " to " + owner.getName() + "'s chest at " + loc.getWorld().getName() + "," + loc.getBlockX() + "," +loc.getBlockY() + "," + loc.getBlockZ() + chest.getCommentString(); } else { //(count < savedcount) msg = player.getName() + " removed " + diff + " units of " + material + " from " + owner.getName() + "'s chest at " + loc.getWorld().getName() + "," + loc.getBlockX() + "," +loc.getBlockY() + "," + loc.getBlockZ() + chest.getCommentString(); } server.getLogger().info( "[AdvancedChest]" + msg); plugin.getMessageWrapper().sendMessage("system", owner, msg); } } } } ItemCount countItems(ItemStack[] input) { ItemCount output = new ItemCount(); for (int i=0; i