/* * Copyright (C) 2011 Moritz Schmale <narrow.m@gmail.com> * * DropChest is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>. */ package com.narrowtux.dropchest; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.WorldCreator; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.ContainerBlock; import org.bukkit.entity.Player; import org.bukkit.entity.StorageMinecart; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.PluginManager; import com.narrowtux.dropchest.api.DropChestFillEvent; public class DropChestItem implements Serializable{ private static final long serialVersionUID = 2940482362395614394L; private ContainerBlock containerBlock; private int radius; private int delay = 0; private String owner = ""; private boolean protect = false; private String name = ""; private int id; private HashMap<FilterType,List<Material > > filter = new HashMap<FilterType,List<Material> >(); private boolean warnedNearlyFull = false; private DropChest plugin; private DropChestMinecartAction minecartAction = DropChestMinecartAction.IGNORE; private boolean loadedProperly = true; private static int currentId = 1; private Location loc = null; private long lastRedstoneDrop = 0; public DropChestItem(ContainerBlock containerBlock, int radius, Block block, DropChest plugin) { this.containerBlock = containerBlock; this.radius = radius; this.plugin = plugin; loc = new Location(block.getWorld(), block.getX(), block.getY(), block.getZ()); id = currentId++; initFilter(); } public DropChestItem(String loadString, String fileVersion, DropChest plugin) { this.plugin = plugin; initFilter(); load(loadString, fileVersion); } public DropChestItem(Map<String, Object> loadMap, DropChest plugin){ this.plugin = plugin; initFilter(); load(loadMap); } private void initFilter(){ List<Material> f = new ArrayList<Material>(); filter.put(FilterType.SUCK, f); f = new ArrayList<Material>(); filter.put(FilterType.PUSH, f); f = new ArrayList<Material>(); filter.put(FilterType.PULL, f); } public ContainerBlock getChest() { if(getBlock().getState() instanceof ContainerBlock){ containerBlock = (ContainerBlock)getBlock().getState(); return containerBlock; } else { return null; } } public Inventory getInventory(){ //First, check if this is a double chest. BlockFace faces[] = {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}; for(BlockFace face:faces){ Block other = getBlock().getRelative(face); if(other.getType().equals(Material.CHEST)){ if(other.getState() instanceof ContainerBlock){ Inventory inventories[] = {getChest().getInventory(), ((ContainerBlock)other.getState()).getInventory()}; return new DropChestInventory(inventories); } } } return getChest().getInventory(); } public void setChest(Chest chest) { this.containerBlock = chest; } public int getRadius() { return radius; } public void setRadius(int radius) { if(radius<0) { getOwnerPlayer().sendMessage(ChatColor.RED.toString()+"Chest radius was negative!, radius changed to 2"); radius = 2; } else if(radius==0) getOwnerPlayer().sendMessage(ChatColor.RED.toString()+"Chest radius is 0, the chest will not suck"); this.radius = radius; } public void setDelay(int delay) { this.delay = (delay >= 0 ? delay : 0); } public int getDelay() { return delay; } public Player getOwnerPlayer(){ return Bukkit.getServer().getPlayer(getOwner()); } public double getPercentFull(){ Inventory inv; try{ inv = getInventory(); } catch(NullPointerException e){ if(getBlock().getChunk().isLoaded()){ plugin.removeChest(this); plugin.log.log(Level.WARNING, "Removed 1 Chest because it isn't there any more."); } return 0; } int stacks = inv.getSize(); int maxStackSize = 0; int totalItems = 0; for(int j = 0; j<stacks; j++){ ItemStack istack = inv.getItem(j); if(istack!=null){ totalItems+=istack.getAmount(); if(istack.getTypeId()==0){ maxStackSize+=64; } else { maxStackSize+=istack.getMaxStackSize(); } } } double percent = (double)totalItems/(double)maxStackSize; if(percent<plugin.config.getWarnFillStatus()/100) warnedNearlyFull = false; return percent; } public void warnNearlyFull(){ if(!warnedNearlyFull&&plugin.config.getWarnFillStatus()!=-1){ String warnString = plugin.config.getWarnString(); warnString = warnString.replaceAll("\\$name", getName()); warnString = warnString.replaceAll("\\$fill", String.valueOf((int)(getPercentFull()*100.0))); warnString = warnString.replaceAll("\\$owner", getOwner()); Player player = plugin.getServer().getPlayer(getOwner()); if(player!=null&&player.isOnline()){ player.sendMessage(warnString); } else { plugin.getServer().broadcastMessage(warnString); } warnedNearlyFull = true; } } public List<Material> getFilter(FilterType filterType){ return filter.get(filterType); } public HashMap<Integer, ItemStack> addItem(ItemStack item, FilterType filterType) { DropChestFillEvent fillEvent = new DropChestFillEvent(this); PluginManager pm = plugin.getServer().getPluginManager(); getChest(); if(filter.get(filterType).size()==0&&filterType==FilterType.SUCK){ HashMap<Integer, ItemStack> ret = getInventory().addItem(item); pm.callEvent(fillEvent); return ret; } else { for(Material m : filter.get(filterType)) { if(m.getId()==item.getTypeId()){ pm.callEvent(fillEvent); return getInventory().addItem(item); } } HashMap<Integer, ItemStack> ret = new HashMap<Integer, ItemStack>(); ret.put(0, item); return ret; } } /** * @param minecartAction the minecartAction to set */ public void setMinecartAction(DropChestMinecartAction minecartAction) { this.minecartAction = minecartAction; } /** * @return the minecartAction */ public DropChestMinecartAction getMinecartAction() { return minecartAction; } public void setRedstone(boolean value){ Block below = getBlock().getRelative(BlockFace.DOWN); if(below.getTypeId() == Material.LEVER.getId()){ byte data = below.getData(); if(value){ data=0x8|0x5; } else { data=0x5; } below.setData(data); } } public void triggerRedstone(){ setRedstone(true); Timer timer = new Timer(); timer.schedule(new RedstoneTrigger(this), 1000); } public void dropAll(){ if(isProtect()){ return; } World world = getBlock().getWorld(); Location loc = getBlock().getLocation(); for(int i = 0; i<containerBlock.getInventory().getSize();i++){ ItemStack item = containerBlock.getInventory().getItem(i); if(item.getAmount()!=0){ world.dropItem(loc, item); containerBlock.getInventory().clear(i); } } Date date = new Date(); lastRedstoneDrop = date.getTime(); } private void load(String loadString, String fileVersion) { if(fileVersion.equalsIgnoreCase("0.0")){ //Obsolete } else if(fileVersion.equals("0.1")||fileVersion.equals("0.2")||fileVersion.equals("0.3")||fileVersion.equals("0.4")||fileVersion.equals("0.5")||fileVersion.equals("0.6")||fileVersion.equals("0.7")||fileVersion.equals("0.8")){ String splt[] = loadString.split(";"); if(splt.length>=1){ String data[] = splt[0].split(","); String filters[]; if(splt.length==2||splt.length==4){ for(int ft=1;ft<splt.length;ft++){ filters = splt[ft].split(","); FilterType type = null ; switch(ft){ case 1: type = FilterType.SUCK; break; case 2: type = FilterType.PULL; break; case 3: type = FilterType.PUSH; break; default: type = FilterType.SUCK; break; } for(int i = 0; i<filters.length; i++) { List<Material> fi = getFilter(type); if(!filters[i].isEmpty()){ Material m = null; try{ m = Material.valueOf(filters[i]); } catch (IllegalArgumentException e){ m = null; } if(m!=null) { fi.add(m); } } } } } if(data.length>=6){ Double x,y,z; long worldid; World world = null; x = Double.valueOf(data[0]); y = Double.valueOf(data[1]); z = Double.valueOf(data[2]); radius = Integer.valueOf(data[3]); try{ setMinecartAction(DropChestMinecartAction.valueOf(data[5])); } catch(java.lang.IllegalArgumentException e){ setMinecartAction(DropChestMinecartAction.IGNORE); } org.bukkit.World.Environment env = org.bukkit.World.Environment.NORMAL; if(fileVersion.equals("0.3")){ env = org.bukkit.World.Environment.valueOf(data[6]); } if(fileVersion.equalsIgnoreCase("0.1")){ worldid = Long.valueOf(data[4]); //world = plugin.getWorldWithId(worldid); } else { world = plugin.getServer().getWorld(data[4]); if(world==null) { world = plugin.getServer().createWorld(new WorldCreator(data[4]).environment(env)); } } if(fileVersion.equals("0.4")){ id = Integer.valueOf(data[7]); currentId = Math.max(currentId, id+1); } else { id = currentId++; } if((fileVersion.equals("0.6")||fileVersion.equals("0.7"))||fileVersion.equals("0.8")&&data.length>=9){ setName(data[8]); } if(fileVersion.equals("0.7")||fileVersion.equals("0.8")&&data.length>=11){ setOwner(data[9]); setProtect(Boolean.valueOf(data[10])); } if(fileVersion.equals("0.8")){ setDelay(Integer.valueOf(data[11])); } if(world!=null){ Block b = world.getBlockAt((int)(double)x,(int)(double)y,(int)(double)z); if(acceptsBlockType(b.getType())){ this.containerBlock = (ContainerBlock)b.getState(); this.loc = b.getLocation(); if(this.containerBlock==null){ loadedProperly = false; System.out.println("Chest is null..."); } } else { System.out.println("Block is not accepted!"); loadedProperly = false; } } else { System.out.println("World not found!"); loadedProperly = false; } } else { System.out.println("Number of columns not accepted!"); loadedProperly = false; return; } } else { System.out.println("Number of columns not accepted!"); loadedProperly=false; } } else { System.out.println("File has invalid version: "+fileVersion); loadedProperly=false; } } public String save() { // VERSION!!!! 0.7 String line = ""; line = String.valueOf(loc.getX()) + "," + String.valueOf(loc.getY()) + "," + String.valueOf(loc.getZ()) + "," + String.valueOf(getRadius()) + "," + String.valueOf(loc.getWorld().getName()); line += ","; line += "," + String.valueOf(loc.getWorld().getEnvironment()); line += "," + String.valueOf(id); line += "," + name; line += "," + getOwner(); line += "," + String.valueOf(isProtect()); line += "," + getDelay(); //Filter saving for(FilterType type : FilterType.values()){ line += ";"; int i = 0; for(Material m:getFilter(type)) { if(i>0){ line+=","; } line+=m.name(); i++; } if(getFilter(type).size()==0){ line+=type.toString(); } } line+="\n"; return line; } public boolean isLoadedProperly() { return loadedProperly; } public Block getBlock() { return loc.getBlock(); } public void setBlock(Block block) { this.loc = block.getLocation(); } static public boolean acceptsBlockType(Material m){ return m.getId()==Material.CHEST.getId() ||m.getId()==Material.DISPENSER.getId() ||m.getId()==Material.FURNACE.getId() ||m.getId()==Material.BURNING_FURNACE.getId(); } public int getId() { return id; } public String listString(){ String ret = ""; ret+=getName(); double p = getPercentFull(); ret+=" | "+(int)(p*100)+"%"; ret+=" | "+String.valueOf(getFilter(FilterType.SUCK).size()+getFilter(FilterType.PUSH).size()+getFilter(FilterType.PULL).size())+" "; ret+=" | "+String.valueOf(getRadius()); return ret; } @SuppressWarnings("unused") public void minecartAction(StorageMinecart storage){ ContainerBlock chest = getChest(); Inventory chinv = chest.getInventory(); Inventory miinv = storage.getInventory(); if(false){ //item stacks of furnaces: // stack 1: fuel, can be either wood or coal // stack 0: meltables, can be ores, sand, cobblestone, log and cactus // stack 2: products ItemStack items[] = miinv.getContents(); ItemStack furn[] = chinv.getContents(); for(int i = 0; i<items.length;i++) { ItemStack is = items[i]; if(is.getType().equals(Material.COAL) ||is.getType().equals(Material.WOOD) ||is.getType().equals(Material.LAVA_BUCKET)){ //this is fuel ItemStack fs = furn[1]; if(fs.getType().equals(is.getType())||fs.getAmount()==0){ int remove = 0; if(fs.getAmount()==0){ remove = 1; } fs.setType(is.getType()); fs.setData(is.getData()); if(fs.getAmount()+is.getAmount()-remove<=64){ fs.setAmount(fs.getAmount()+is.getAmount()-remove); miinv.remove(is); } else { int remaining = fs.getAmount()+is.getAmount()-64; fs.setAmount(64); is.setAmount(remaining); miinv.setItem(i, is); } chinv.setItem(0, fs); } } if(is.getType().toString().contains("ORE")|| is.getType().equals(Material.LOG)|| is.getType().equals(Material.CACTUS)|| is.getType().equals(Material.SAND)|| is.getType().equals(Material.COBBLESTONE)){ //this is burnable ItemStack fs = furn[0]; if(fs.getType().equals(is.getType())||fs.getAmount()==0){ int remove = 0; if(fs.getAmount()==0){ remove = 1; } fs.setType(is.getType()); fs.setData(is.getData()); if(fs.getAmount()+is.getAmount()-remove<=64){ fs.setAmount(fs.getAmount()+is.getAmount()-remove); miinv.remove(is); } else { int remaining = fs.getAmount()+is.getAmount()-64; fs.setAmount(64); is.setAmount(remaining); miinv.setItem(i, is); } chinv.setItem(0, fs); } } } if(furn[2].getAmount()!=0){ ItemStack items1 = furn[2]; HashMap<Integer,ItemStack> hash = miinv.addItem(items1); if(hash.size()!=0){ items1.setAmount(items1.getAmount()-hash.get(0).getAmount()); } chinv.remove(items1); } } else { for(int i = 0; i<chinv.getSize();i++){ ItemStack items = chinv.getItem(i); if(items.getAmount()!=0){ if(getFilter(FilterType.PUSH).contains(items.getType())){ HashMap<Integer,ItemStack> hash = miinv.addItem(items); if(hash.size()!=0){ ItemStack ret=hash.get(0); items.setAmount(ret.getAmount()); chinv.setItem(i, items); }else { chinv.clear(i); } } } } for(int i = 0; i<miinv.getSize();i++){ ItemStack items = miinv.getItem(i).clone(); if(items.getAmount()!=0){ if(getFilter(FilterType.PULL).contains(items.getType())){ HashMap<Integer,ItemStack> hash = addItem(items, FilterType.PULL); if(hash.size()!=0){ ItemStack ret=hash.get(0); items.setAmount(ret.getAmount()); miinv.setItem(i, items); } else { miinv.clear(i); } } } } } } public String info(){ String ret = ChatColor.WHITE.toString(); String filterString = ""; ret+="ID: "+ChatColor.YELLOW+getId()+ChatColor.WHITE+ " Name: "+ChatColor.YELLOW+getName()+ ChatColor.WHITE+" Radius: "+ChatColor.YELLOW+getRadius()+ ChatColor.WHITE+" Owner: "+ChatColor.YELLOW+getOwner()+"\n"; for(FilterType type:FilterType.values()){ List<Material> filter = getFilter(type); if(filter.size()!=0) { filterString+=ChatColor.AQUA+type.toString()+":\n"; boolean useId = false; if(filter.size()<5){ useId = false; } else { useId = true; } for(int i = 0; i<filter.size();i++){ Material m = filter.get(i); filterString+=ChatColor.YELLOW.toString(); if(useId){ filterString+=m.getId(); } else { filterString+=m.toString(); } if(i+1!=filter.size()){ filterString+=ChatColor.WHITE+", "; } else { filterString+=ChatColor.WHITE+"\n"; } } } } if(!filterString.equals("")){ ret+=ChatColor.AQUA+"Filters:\n"; ret+=filterString; } return ret; } public boolean isChest(){ return getBlock().getType().equals(Material.CHEST); } public boolean isFurnace(){ return getBlock().getType().equals(Material.FURNACE) || getBlock().getType().equals(Material.BURNING_FURNACE); } public boolean isDispenser(){ return getBlock().getType().equals(Material.DISPENSER); } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the name */ public String getName() { if(name.isEmpty()){ return "#"+String.valueOf(id); } return name; } /** * @return the location */ public Location getLocation() { return loc; } /** * @param owner the owner to set */ public void setOwner(String owner) { this.owner = owner; } /** * @return the owner */ public String getOwner() { return owner; } /** * @param protect the protect to set */ public void setProtect(boolean protect) { this.protect = protect; } /** * @return the protect */ public boolean isProtect() { if(!plugin.config.isLetUsersProtectChests()){ return false; } return protect; } /** * @return the lastRedstoneDrop */ public long getLastRedstoneDrop() { return lastRedstoneDrop/1000; } public DropChestPlayer getOwnerDCPlayer() { return DropChestPlayer.getPlayerByName(getOwner()); } public void save(Map<String, Object> chest) { chest.put("id", getId()); chest.put("name", getName()); chest.put("owner", getOwner()); chest.put("delay", getDelay()); chest.put("protect", isProtect()); chest.put("radius", getRadius()); chest.put("location", locationToString(loc)); Map<String, Object> filters = new HashMap<String, Object>(); for(FilterType type:FilterType.values()){ ArrayList<String> filter = new ArrayList<String>(); for(Material mat:getFilter(type)){ filter.add(""+mat.getId()); } filters.put(type.toString(), filter); } chest.put("filter", filters); } @SuppressWarnings("unchecked") private void load(Map<String, Object> loadMap) { id = (Integer)loadMap.get("id"); setName((String)loadMap.get("name")); setOwner((String)loadMap.get("owner")); setDelay((Integer)loadMap.get("delay")); setProtect((Boolean)loadMap.get("protect")); setRadius((Integer)loadMap.get("radius")); loc = locationFromString((ArrayList<String>)loadMap.get("location")); Map<String, Object> filters = (Map<String, Object>)loadMap.get("filter"); for(String typename:filters.keySet()){ FilterType type = FilterType.valueOf(typename); List<Material> filter = getFilter(type); ArrayList<String> items = (ArrayList<String>)filters.get(typename); for(String item:items) { filter.add(Material.getMaterial(Integer.valueOf(item))); } } } private String [] locationToString(Location loc){ String [] ret = { loc.getWorld().getName(), loc.getWorld().getEnvironment().toString(), loc.getBlockX()+"", loc.getBlockY()+"", loc.getBlockZ()+"" }; return ret; } private Location locationFromString(ArrayList<String> args){ World w = Bukkit.getServer().createWorld(new WorldCreator(args.get(0)).environment(Environment.valueOf(args.get(1)))); int x = Integer.valueOf(args.get(2)); int y = Integer.valueOf(args.get(3)); int z = Integer.valueOf(args.get(4)); return new Location(w, x, y, z); } }