package com.entryrise.lagassist.hoppers; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.Hopper; import org.bukkit.entity.EntityType; import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import com.entryrise.lagassist.Data; import com.entryrise.lagassist.Main; import com.entryrise.lagassist.utils.Cache; import com.entryrise.lagassist.utils.Others; import com.entryrise.lagassist.utils.V1_12; import com.entryrise.lagassist.utils.V1_13; import com.entryrise.lagassist.utils.V1_8; import com.entryrise.lagassist.utils.VersionMgr; public class ChunkHoppers implements Listener { // The Cachetime represents how often the cache should be removed // and the tiles rechecked. private static Cache tilecache = new Cache(40); public static boolean mobhoppers; private static double multiplier; private static List reasons; private static String hoppermode; public static String customname; private static Item dropplayer; private class HopperComparator implements Comparator { Location initial; public HopperComparator(Location initial) { this.initial = initial; } @Override public int compare(Hopper h1, Hopper h2) { return (int) h1.getLocation().distance(initial) - (int) h2.getLocation().distance(initial); } } public static void Enabler(boolean reload) { hoppermode = Main.config.getString("hopper-check.chunk-hoppers.mode"); mobhoppers = Main.config.getDouble("hopper-check.chunk-hoppers.mob-hopper.maxtps") >= 20; multiplier = Main.config.getDouble("hopper-check.chunk-hoppers.mob-hopper.multiplier"); reasons = Main.config.getStringList("hopper-check.chunk-hoppers.mob-hopper.spawn-reasons"); customname = ChatColor.translateAlternateColorCodes('&', Main.config.getString("hopper-check.chunk-hoppers.define")); tilecache.clear(); if (!reload) { Main.p.getServer().getPluginManager().registerEvents(new ChunkHoppers(), Main.p); runTask(); } HopperFilter.Enabler(reload); SellHoppers.Enabler(reload); } private static void runTask() { Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.p, new Runnable() { @Override public void run() { tilecache.tick(); } }, 1L, 1L); } public static void giveChunkHopper(Player p, int amount) { Inventory inv = p.getInventory(); ItemStack itm = getCustomHopper(amount); int empty = inv.firstEmpty(); if (empty == -1) { p.getLocation().getWorld().dropItem(p.getLocation(), itm); return; } p.getInventory().addItem(itm); } private static Material getMaterial(EntityType et) { String loc = "hopper-check.chunk-hoppers.mob-hopper.filter-items." + et.toString().toLowerCase(); if (!Main.config.contains(loc)) { return null; } return Material.valueOf(Main.config.getString(loc)); } private List getHoppers(Chunk chk, Material mat) { List hoppers = new ArrayList(); if (!tilecache.isCached(chk)) { tilecache.putCached(chk, chk.getTileEntities()); } for (BlockState b : tilecache.getCached(chk)) { if (!(b instanceof Hopper)) { continue; } Hopper h = (Hopper) b; String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h); // Check if not default; and if it isn't default; check if the string is null or // it isn't custom and continue. if (!customname.equalsIgnoreCase("DEFAULT") && (stg == null || !stg.equals(customname))) { continue; } if (!HopperFilter.isAllowed(h.getLocation(), mat)) { continue; } hoppers.add((Hopper) b); } return hoppers; } private ItemStack spreadItemInHoppers(List hoppers, ItemStack itm, Location loc) { ItemStack remainder = itm.clone(); if (isCustomHopper(remainder)) { return remainder; } if (hoppermode.equalsIgnoreCase("RANDOM")) { Collections.shuffle(hoppers); } else if (hoppermode.equalsIgnoreCase("CLOSEST")) { Collections.sort(hoppers, new HopperComparator(loc)); } for (Hopper hopper : hoppers) { Inventory inv = hopper.getInventory(); if (SellHoppers.attemptSell(hopper, itm)) { return null; } Map remainers = inv.addItem(remainder); if (remainers.size() < 1) { return null; } remainder = remainers.get(0); if (remainder == null) { return null; } } return remainder; } private static ItemStack chopper; public static boolean isCustomHopper(ItemStack itm) { if (chopper == null) { chopper = getCustomHopper(1); } itm = itm.clone(); itm.setAmount(1); return itm.isSimilar(chopper); } public static ItemStack getCustomHopper(int amount) { ItemStack itm = new ItemStack(Material.valueOf("HOPPER"), amount); ItemMeta imeta = itm.getItemMeta(); if (!customname.equalsIgnoreCase("DEFAULT")) { imeta.setDisplayName(customname); } // Make it work with the unbreakable check. VersionMgr.setUnbreakable(imeta, true); imeta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); itm.setItemMeta(imeta); return itm; } @EventHandler(priority = EventPriority.HIGHEST) public void onPlace(BlockPlaceEvent e) { if (e.isCancelled()) { return; } if (customname.equalsIgnoreCase("DEFAULT")) { return; } ItemStack itm = e.getItemInHand(); if (itm == null) { return; } if (!itm.hasItemMeta()) { return; } ItemMeta imeta = itm.getItemMeta(); if (!imeta.hasDisplayName()) { return; } String name = imeta.getDisplayName(); if (!name.equalsIgnoreCase(customname)) { return; } if (!VersionMgr.isUnbreakable(imeta)) { e.setCancelled(true); return; } // System.out.println("SET OWNER"); // Set owner Data.setOwningPlayer(e.getBlockPlaced().getLocation(), e.getPlayer()); tilecache.remove(e.getBlockPlaced().getChunk()); } @EventHandler(priority = EventPriority.HIGHEST) public void onBreak(BlockBreakEvent e) { if (e.isCancelled()) { return; } if (customname.equalsIgnoreCase("DEFAULT")) { return; } Block b = e.getBlock(); BlockState bstate = b.getState(); if (!(bstate instanceof Hopper)) { return; } Hopper h = (Hopper) bstate; String stg = VersionMgr.isV1_8() ? V1_8.getHopperName(h) : V1_12.getHopperName(h); if (stg == null) { return; } if (!stg.equals(customname)) { return; } Data.deleteHopper(h); b.setType(Material.AIR); // dropplayer = b.getWorld().dropItemNaturally(b.getLocation(), getCustomHopper(1)); dropplayer = Others.giveOrDrop(e.getPlayer(), getCustomHopper(1)); // e.getPlayer().getInventory().addItem(getCustomHopper(1)); tilecache.remove(b.getChunk()); } @EventHandler public void playerDrop(PlayerDropItemEvent e) { if (e.isCancelled()) { return; } dropplayer = e.getItemDrop(); } @EventHandler public void onItemDrop(ItemSpawnEvent e) { if (e.isCancelled()) { return; } Item itm = e.getEntity(); ItemStack its = itm.getItemStack(); Material mat = its.getType(); if (itm.equals(dropplayer)) { return; } Chunk chk = itm.getLocation().getChunk(); List hoppers = getHoppers(chk, mat); if (hoppers.size() < 1) { return; } ItemStack remainder = spreadItemInHoppers(hoppers, itm.getItemStack(), itm.getLocation()); if (remainder == null) { e.setCancelled(true); return; } itm.setItemStack(remainder); } @EventHandler public void onCreatureSpawn(CreatureSpawnEvent e) { if (e.isCancelled()) { return; } if (!reasons.contains(e.getSpawnReason().toString())) { return; } if (!mobhoppers) { return; } LivingEntity ent = e.getEntity(); Material mat = getMaterial(ent.getType()); if (mat == null) { return; } Chunk chk = ent.getLocation().getChunk(); List hoppers = getHoppers(chk, mat); for (ItemStack itm : V1_13.getLootTable(ent)) { ItemStack buffed = itm.clone(); buffed.setAmount((int) (itm.getAmount() * multiplier)); spreadItemInHoppers(hoppers, buffed, ent.getLocation()); } e.setCancelled(true); // TODO: FINISH CHECK } }