/*
* Copyright 2011 Tyler Blair. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and contributors and should not be interpreted as representing official policies,
* either expressed or implied, of anybody else.
*/
package com.griefcraft.modules.flag;
import com.griefcraft.lwc.LWC;
import com.griefcraft.model.Flag;
import com.griefcraft.model.Protection;
import com.griefcraft.scripting.JavaModule;
import com.griefcraft.util.config.Configuration;
import com.narrowtux.showcase.Showcase;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
public class MagnetModule extends JavaModule {
private Configuration configuration = Configuration.load("magnet.yml");
/**
* If this module is enabled
*/
private boolean enabled = false;
/**
* The item blacklist
*/
private List<Integer> itemBlacklist;
/**
* The radius around the container in which to suck up items
*/
private int radius;
/**
* How many items to check each time
*/
private int perSweep;
/**
* The current entity queue
*/
private final Queue<MagnetNode> items = new LinkedList<MagnetNode>();
private class MagnetNode { Item item; Protection protection; }
// does all of the work
// searches the worlds for items and magnet chests nearby
private class MagnetTask implements Runnable {
public void run() {
Server server = Bukkit.getServer();
LWC lwc = LWC.getInstance();
// Do we need to requeue?
if (items.size() == 0) {
for (World world : server.getWorlds()) {
for (Entity entity : world.getEntities()) {
if (!(entity instanceof Item)) {
continue;
}
Item item = (Item) entity;
ItemStack stack = item.getItemStack();
// check if it is in the blacklist
if (itemBlacklist.contains(stack.getTypeId())) {
continue;
}
// check if the item is valid
if (stack.getAmount() <= 0) {
continue;
}
if (item.isDead()) {
continue;
}
if (isShowcaseItem(item)) {
// it's being used by the Showcase plugin ... ignore it
continue;
}
// has the item been living long enough?
if (item.getPickupDelay() > item.getTicksLived()) {
continue; // a player wouldn't have had a chance to pick it up yet
}
Location location = item.getLocation();
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
List<Protection> protections = lwc.getPhysicalDatabase().loadProtections(world.getName(), x, y, z, radius);
for (Protection protection : protections) {
if (protection.hasFlag(Flag.Type.MAGNET)) {
protection.getBlock();
// we only want inventory blocks
if (!(protection.getBlock().getState() instanceof InventoryHolder)) {
continue;
}
MagnetNode node = new MagnetNode();
node.item = item;
node.protection = protection;
items.offer(node);
break;
}
}
}
}
}
// Throttle amount of items polled
int count = 0;
MagnetNode node;
while ((node = items.poll()) != null) {
Item item = node.item;
Protection protection = node.protection;
World world = item.getWorld();
ItemStack itemStack = item.getItemStack();
Location location = item.getLocation();
Block block = protection.getBlock();
if (item.isDead()) {
continue;
}
// Remove the items and suck them up :3
Map<Integer, ItemStack> remaining;
try {
remaining = lwc.depositItems(block, itemStack);
} catch (Exception e) {
lwc.log("Exception occurred while depositing into the block: " + block.toString());
e.printStackTrace();
return;
}
// we cancelled the item drop for some reason
if (remaining == null) {
continue;
}
if (remaining.size() == 1) {
ItemStack other = remaining.values().iterator().next();
if (itemStack.getTypeId() == other.getTypeId() && itemStack.getAmount() == other.getAmount()) {
continue;
}
}
// remove the item on the ground
item.remove();
// if we have a remainder, we need to drop them
if (remaining.size() > 0) {
for (ItemStack stack : remaining.values()) {
world.dropItemNaturally(location, stack);
}
}
if (count > perSweep) {
break;
}
count ++;
}
}
}
/**
* Check for the Showcase plugin and if it exists we also want to make sure the block doesn't have a showcase
* on it.
*
* @param item
* @return
*/
private boolean isShowcaseItem(Item item) {
if (item == null) {
return false;
}
// check for the showcase plugin
boolean hasShowcase = Bukkit.getServer().getPluginManager().getPlugin("Showcase") != null;
if (hasShowcase) {
return Showcase.instance.getItemByDrop(item) != null;
}
return false;
}
@Override
public void load(LWC lwc) {
enabled = configuration.getBoolean("magnet.enabled", false);
itemBlacklist = new ArrayList<Integer>();
radius = configuration.getInt("magnet.radius", 3);
perSweep = configuration.getInt("magnet.perSweep", 20);
if (!enabled) {
return;
}
// get the item blacklist
List<String> temp = configuration.getStringList("magnet.blacklist", new ArrayList<String>());
for (String item : temp) {
Material material = Material.matchMaterial(item);
if (material != null) {
itemBlacklist.add(material.getId());
}
}
// register our search thread schedule
MagnetTask searchThread = new MagnetTask();
lwc.getPlugin().getServer().getScheduler().scheduleSyncRepeatingTask(lwc.getPlugin(), searchThread, 50, 50);
}
}