/**
* Copyright (C) 2011 Jacob Scott <jascottytechie@gmail.com> Description: thread
* to scan for chest collection
*
* This program 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/>.
*/
package me.jascotty2.chestharvester;
import me.jascotty2.bukkit.bettershop3.BetterShop3;
import me.jascotty2.libv01.bukkit.inventory.ChestManip;
import me.jascotty2.libv01.bukkit.inventory.ItemStackManip;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Chest;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.StorageMinecart;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class CollectorScanner implements Runnable {
public long interval = 1000;
private int taskID = -1;
ChestHarvester plugin;
public CollectorScanner(ChestHarvester plugin) {
this.plugin = plugin;
}
public void start() {
start(interval);
}
public void start(long wait) {
//(new Timer()).scheduleAtFixedRate(this, wait, wait);
// 20 ticks per second
this.interval = wait;
taskID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this, 100, (wait * 20) / 1000);
}
public void cancel() {
if (taskID != -1) {
plugin.getServer().getScheduler().cancelTask(taskID);
taskID = -1;
}
}
@Override
public void run() {
// long st = System.currentTimeMillis();
dropChestScan();
// System.out.println("scan latency: " + (System.currentTimeMillis() - st));
}
/**
* scans for drops, then puts them into the first chest in a 1-block radius
* that can hold them
*/
public void dropChestScan() {
try {
Map<Chest, ItemStack[]> chests = new HashMap<Chest, ItemStack[]>();
Map<StorageMinecart, ItemStack[]> carts = new HashMap<StorageMinecart, ItemStack[]>();
for (World world : plugin.getServer().getWorlds()) {
String w = world.getName().toLowerCase();
if (plugin.config.disabledWorlds.contains(w)) {
continue;
}
for (Entity e : ChestHarvester.plugin.config.storageCartsEmpty
? world.getEntitiesByClasses(Item.class, StorageMinecart.class)
: world.getEntitiesByClass(Item.class)) {
double close = Double.POSITIVE_INFINITY, d;
Chest closest = null;
for (Block block : getScanBlocks(e.getLocation().getBlock())) {
if (block.getType() == Material.CHEST) {
// if (plugin.betterShopPlugin != null
// && BetterShop.getSettings().chestShopEnabled
// && BetterShop.getChestShop() != null
// && BetterShop.getChestShop().hasChestShop(block)) {
// continue;
// }
d = block.getLocation().add(.5, .5, .5).distance(e.getLocation());
if (d < close) {
close = d;
closest = (Chest) block.getState();
}
}
}
if (closest != null) {
ItemStack is[] = chests.get(closest);
if (is == null) {
is = closest.getInventory().getContents();//ChestManip.getContents(closest);
for (int i = 0; i < is.length; ++i) {
if (is[i] == null) {
is[i] = new ItemStack(0, 0);
}
}
chests.put(closest, is);
}
if (e instanceof Item) {
Item item = (Item) e;
ItemStack no = ItemStackManip.add(is, item.getItemStack(), plugin.config.autoStack);
if (no.getAmount() == 0) {
item.remove();
} else {
item.setItemStack(no);
}
} else { // is a StorageMinecart
StorageMinecart cart = (StorageMinecart) e;
Inventory inv = cart.getInventory();
for (int i = 0; i < inv.getSize(); ++i) {
ItemStack item = inv.getItem(i);
if (item != null && item.getAmount() > 0
&& ItemStackManip.amountCanHold(is, item, plugin.config.autoStack) > 0) {
ItemStack no = ItemStackManip.add(is, item, plugin.config.autoStack);
if (no.getAmount() == 0) {
item.setAmount(0);
inv.setItem(i, null);
} else {
item.setAmount(no.getAmount());
inv.setItem(i, item);
}
}
}
}
} else if (plugin.config.storageCartsCollect && e instanceof Item) {
List<Entity> nearby = e.getNearbyEntities(plugin.config.scanRange * 2, plugin.config.scanRange * 2, plugin.config.scanRange * 2);
close = Double.POSITIVE_INFINITY;
StorageMinecart closestCart = null;
for (Entity en : nearby) {
if (en instanceof StorageMinecart) {
d = en.getLocation().distance(e.getLocation());
if (d < close) {
close = d;
closestCart = (StorageMinecart) en;
}
}
}
if (closestCart != null) {
ItemStack[] inv = carts.get(closestCart);
if (inv == null) {
inv = closestCart.getInventory().getContents();
carts.put(closestCart, inv);
}
ItemStack no = ItemStackManip.add(inv, ((Item) e).getItemStack(), plugin.config.autoStack);
((Item) e).setItemStack(no);
if (no.getAmount() == 0) {
e.remove();
}
}
}
}
}
for (Map.Entry<Chest, ItemStack[]> c : chests.entrySet()) {
ChestManip.setContents(c.getKey(), c.getValue());
}
for (Map.Entry<StorageMinecart, ItemStack[]> c : carts.entrySet()) {
c.getKey().getInventory().setContents(c.getValue());
}
chests.clear();
carts.clear();
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, e.getMessage(), e);
}
}
public Block[] getScanBlocks(Block b) {
if ((plugin.config.scanRange <= 1 || plugin.config.scanRange > 3)) {
return plugin.config.allDirections
? new Block[]{
b,
b.getRelative(BlockFace.DOWN),
b.getRelative(BlockFace.NORTH),
b.getRelative(BlockFace.EAST),
b.getRelative(BlockFace.SOUTH),
b.getRelative(BlockFace.WEST),
b.getRelative(BlockFace.UP),
b.getRelative(BlockFace.NORTH_WEST),
b.getRelative(BlockFace.NORTH_EAST),
b.getRelative(BlockFace.SOUTH_EAST),
b.getRelative(BlockFace.SOUTH_WEST)}
: new Block[]{
b,
b.getRelative(BlockFace.DOWN),
b.getRelative(BlockFace.NORTH),
b.getRelative(BlockFace.EAST),
b.getRelative(BlockFace.SOUTH),
b.getRelative(BlockFace.WEST)};
} else {
ArrayList<Block> blocks = new ArrayList<Block>();
for (int x = -plugin.config.scanRange;
x <= plugin.config.scanRange; ++x) {
for (int z = -plugin.config.scanRange;
z <= plugin.config.scanRange; ++z) {
for (int y = -plugin.config.scanRange;
y <= (plugin.config.allDirections ? plugin.config.scanRange : 0); ++y) {
Block ab = b.getRelative(x, y, z);
if (plugin.config.allDirections) {
blocks.add(ab);
} else if (b.getLocation().distance(ab.getLocation()) <= plugin.config.scanRange) {
blocks.add(ab);
}
}
}
}
return blocks.toArray(new Block[0]);
}
}
} // end class CollectorScanner