package org.mctourney.autoreferee.util.worldsearch; import java.util.List; import java.util.Set; import org.bukkit.Material; import org.bukkit.SkullType; import org.bukkit.World; import org.bukkit.entity.Boat; import org.bukkit.entity.Enderman; import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Item; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Minecart; import org.bukkit.entity.Sheep; import org.bukkit.entity.Skeleton; import org.bukkit.entity.Skeleton.SkeletonType; import org.bukkit.entity.Villager; import org.bukkit.entity.minecart.ExplosiveMinecart; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.entity.minecart.PoweredMinecart; import org.bukkit.entity.minecart.SpawnerMinecart; import org.bukkit.entity.minecart.StorageMinecart; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import org.mctourney.autoreferee.util.BlockData; /** * Consumes: ObjectiveExhaustionMasterTask.entitychunks<br> * Output: ObjectiveExhaustionMasterTask.found<br> * Cancellation: Self, on depletion * * Searches each chunk for entities with the goal objects * * @author kane */ public class WorkerEntitySearch extends BukkitRunnable { ObjectiveExhaustionMasterTask master; public WorkerEntitySearch(ObjectiveExhaustionMasterTask task) { master = task; } @Override public void run() { World world = master.team.getMatch().getWorld(); Set<BlockData> goals = master.searching; for (int i = 0; i < 15; i++) // 15 chunks per run { Vector vec = master.entitychunks.poll(); if (vec == null) { this.cancel(); return; } Entity[] entities = world.getChunkAt(vec.getBlockX(), vec.getBlockZ()).getEntities(); // actually chunk-coords for (Entity ent : entities) { // Humans, Horses, Storage & Hopper Minecarts if (ent instanceof InventoryHolder) { Inventory inv = ((InventoryHolder) ent).getInventory(); for (ItemStack item : inv.getContents()) submitMatches(item, ent, goals); } // note: players get their armor checked here // the double-check on the held item doesn't really matter if (ent instanceof LivingEntity) { EntityEquipment eq = ((LivingEntity) ent).getEquipment(); for (ItemStack item : eq.getArmorContents()) { submitMatches(item, ent, goals); } submitMatches(eq.getItemInHand(), ent, goals); } // these 3 should be obvious if (ent instanceof FallingBlock) submitMatches(new BlockData(((FallingBlock) ent).getMaterial(), ((FallingBlock) ent).getBlockData()), ent, goals); if (ent instanceof Item) submitMatches(((Item) ent).getItemStack(), ent, goals); if (ent instanceof ItemFrame) submitMatches(((ItemFrame) ent).getItem(), ent, goals); // drops wood when destroyed if (ent instanceof Boat) submitMatches(new BlockData(Material.WOOD), ent, goals); // endermen can carry blocks...possibly into other lane? interesting, investigate later if (ent instanceof Enderman) { MaterialData carried = ((Enderman) ent).getCarriedMaterial(); submitMatches(new BlockData(carried.getItemType(), carried.getData()), ent, goals); } // break minecarts to get the blocks used to craft if (ent instanceof Minecart) { if (ent instanceof ExplosiveMinecart) submitMatches(new BlockData(Material.TNT), ent, goals); else if (ent instanceof HopperMinecart) submitMatches(new BlockData(Material.HOPPER), ent, goals); else if (ent instanceof PoweredMinecart) submitMatches(new BlockData(Material.FURNACE), ent, goals); // spawners can spawn entities with EntityEquipment on else if (ent instanceof SpawnerMinecart) { // XXX todo: spawners } else if (ent instanceof StorageMinecart) submitMatches(new BlockData(Material.CHEST), ent, goals); } // sheep can be sheared or killed for wool blocks if (ent instanceof Sheep) submitMatches(new BlockData(Material.WOOL, ((Sheep) ent).getColor().getWoolData()), ent, goals); // wither skele skulls if (ent instanceof Skeleton) { if (((Skeleton) ent).getSkeletonType() == SkeletonType.WITHER) submitMatches(new BlockData(Material.SKULL, (byte) SkullType.WITHER.ordinal()), ent, goals); } // trade for goal blocks if (ent instanceof Villager) { // FIXME https://github.com/Bukkit/Bukkit/pull/921 try { List<ItemStack> tradeResults = Unsafe_InspectVillagerTrades.getTradeResults((Villager) ent); for (ItemStack item : tradeResults) submitMatches(item, ent, goals); } catch (Throwable ignored) {} } } } } private void submitMatches(ItemStack item, Entity ent, Set<BlockData> goals) { if (item == null) return; BlockData found = BlockData.fromItemStack(item); submitMatches(found, ent, goals); } private void submitMatches(BlockData found, Entity ent, Set<BlockData> goals) { for (BlockData bd : goals) if (bd.equals(found)) master.found.add(new _Entry<BlockData, Vector>(bd, ent.getLocation().toVector())); } }