package dk.thoerup.bukkit.hoeruputils; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; 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.BlockPlaceEvent; 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; public class SnitchingChest 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 SnitchingChest(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; Block b = player.getTargetBlock(null, 30); Location loc = b.getLocation(); if (b.getTypeId() != 54) { player.sendMessage("[SnitchingChest] Please look at the chest you want to be a snitch"); return true; } Location loc2 = getNeighborChest(loc); SnitchingChestBean chest = chestMap.get(loc); if (chest != null) { if (chest.getOwner().equals(player.getName())) { player.sendMessage("[SnitchingChest] Removing surveillance from chest"); removeChest(loc); } else { player.sendMessage("[SnitchingChest] Chest is already under surveillance"); } return true; } chest = createChest(player.getName(), "", loc); if (loc2 != null) { chest.setDoublechest(true); } addChest(loc, chest); player.sendMessage("[SnitchingChest] Chest is now under surveillance"); return true; } @EventHandler public void onBlockBreak(BlockBreakEvent event) { Location loc = event.getBlock().getLocation(); SnitchingChestBean chest = chestMap.get(loc); if (chest != null) { if (chest.getOwner().equals(event.getPlayer().getName())) { removeChest(loc); event.getPlayer().sendMessage("[SnitchingChest] The destroyed chest was under surveillance"); } else { event.setCancelled(true); event.getPlayer().sendMessage("You can't destroy that chest"); } } } public void addChest(Location loc, SnitchingChestBean chest) { chestMap.put(loc, chest); if (chest.isDoublechest()) { Location loc2 = getNeighborChest(loc); chestMap.put(loc2, chest); } plugin.getDatabase().save(chest); reloadChests(); } void removeChest(Location loc) { SnitchingChestBean chest = chestMap.remove(loc); if (chest != null) { if (chest.isDoublechest()){ Location loc2 = getNeighborChest(loc); chestMap.remove(loc2); } plugin.getDatabase().delete(chest); } } int loadChestsWorker() { List chestlist = plugin.getDatabase().find( SnitchingChestBean.class).findList(); for (SnitchingChestBean 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(); plugin.getLogger().info("[SnitchingChest] loaded " + count + " chests"); } public SnitchingChestBean createChest(String owner, String description, Location loc) { SnitchingChestBean chest = new SnitchingChestBean(); chest.setOwner(owner); chest.setDescription(description); setChestLocation(chest, loc); return chest; } public void setChestLocation(SnitchingChestBean 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, SnitchingChestBean 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) { SnitchingChestBean chest = chestMap.get(chestloc); if (chest != null) { //the neighbor is a snitching chest //SnitchingChestBean newchest = createChest( chest.getOwner(), "", chestloc); //plugin.getDatabase().save(chest); chest.setDoublechest(true); addChest(chestloc, chest); event.getPlayer().sendMessage( "[SnitchingChest] Chest has been expanded" ); } } } /* * how to prevent a user from opening a chest - usefull if SnitchingChest should morph into a LockedChest @EventHandler public void onChestInteract(PlayerInteractEvent event) { if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { Block b = event.getClickedBlock(); if (b.getType() == Material.CHEST) { 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); SnitchingChestBean chest = chestMap.get( loc ); if (chest == null) { return; //chest not surveyed by this plugin } Player player = (Player) event.getPlayer(); if (player.getName().equals(chest.getOwner() )) { return; //chest is owned by it's own player } 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); SnitchingChestBean chest = chestMap.get(loc); if (chest == null) { //chest was not a snitching chest return; } 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 (Integer item : combinedKeyset ) { Integer savedcount = savedContent.get(item); Integer count = content.get(item); if (savedcount == null) savedcount = 0; if (count == null) count = 0; int diff = Math.abs( savedcount - count); if (diff > 0) { String material = Material.getMaterial(item).name(); String msg = null; if (count > savedcount) { msg = player.getName() + " added " + diff + " units of " + material + "(" +item + ") to " + owner.getName() + "'s chest at " + loc.getWorld().getName() + "," + loc.getBlockX() + "," +loc.getBlockY() + "," + loc.getBlockZ(); } else { //(count < savedcount) msg = player.getName() + " removed " + diff + " units of " + material + "(" +item + ") from " + owner.getName() + "'s chest at " + loc.getWorld().getName() + "," + loc.getBlockX() + "," +loc.getBlockY() + "," + loc.getBlockZ(); } plugin.getLogger().info(msg); plugin.getMessageWrapper().sendMessage("system", owner, msg); } } } } ItemCount countItems(ItemStack[] input) { ItemCount output = new ItemCount(); for (int i=0; i