package me.totalfreedom.totalfreedommod; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import lombok.Getter; import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.util.FUtil; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.entity.AreaEffectCloud; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Boat; import org.bukkit.entity.DragonFireball; import org.bukkit.entity.EnderCrystal; import org.bukkit.entity.EnderPearl; import org.bukkit.entity.EnderSignal; import org.bukkit.entity.Entity; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Explosive; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Fireball; import org.bukkit.entity.Firework; import org.bukkit.entity.Item; import org.bukkit.entity.Minecart; import org.bukkit.entity.Projectile; import org.bukkit.entity.ThrownExpBottle; import org.bukkit.entity.ThrownPotion; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; public class EntityWiper extends FreedomService { @Getter private boolean enabled; public static final long ENTITY_WIPE_RATE = 5 * 20L; public static final long ITEM_DESPAWN_RATE = 20L * 20L; public static final int CHUNK_ENTITY_MAX = 20; // private final List> wipables = new ArrayList<>(); // private BukkitTask wipeTask; public EntityWiper(TotalFreedomMod plugin) { super(plugin); wipables.add(EnderCrystal.class); wipables.add(EnderSignal.class); wipables.add(EnderPearl.class); wipables.add(ExperienceOrb.class); wipables.add(Projectile.class); wipables.add(FallingBlock.class); wipables.add(Firework.class); wipables.add(Item.class); wipables.add(ThrownPotion.class); wipables.add(ThrownExpBottle.class); wipables.add(AreaEffectCloud.class); wipables.add(Minecart.class); wipables.add(Boat.class); wipables.add(FallingBlock.class); wipables.add(ArmorStand.class); wipables.add(Fireball.class); wipables.add(DragonFireball.class); } @Override protected void onStart() { if (!ConfigEntry.AUTO_ENTITY_WIPE.getBoolean()) { return; } wipeTask = new BukkitRunnable() { @Override public void run() { wipeEntities(false); } }.runTaskTimer(plugin, ENTITY_WIPE_RATE, ENTITY_WIPE_RATE); } @Override protected void onStop() { FUtil.cancel(wipeTask); wipeTask = null; } public boolean isWipeable(Entity entity) { for (Class c : wipables) { if (c.isAssignableFrom(entity.getClass())) { return true; } } return false; } public int wipeEntities(boolean force) { int removed = 0; Iterator worlds = Bukkit.getWorlds().iterator(); while (worlds.hasNext()) { removed += wipeEntities(worlds.next(), force); } return removed; } public int wipeEntities(World world, boolean force) { int removed = 0; boolean wipeExpl = !ConfigEntry.ALLOW_EXPLOSIONS.getBoolean(); Iterator entities = world.getEntities().iterator(); // Organise the entities in the world Map> cem = new HashMap<>(); while (entities.hasNext()) { final Entity entity = entities.next(); // Explosives if (wipeExpl && Explosive.class.isAssignableFrom(entity.getClass())) { entity.remove(); removed++; } // Only wipeable entities can be wiped (duh!) if (!isWipeable(entity)) { continue; } Chunk c = entity.getLocation().getChunk(); List cel = cem.get(c); if (cel == null) { cem.put(c, new ArrayList<>(Arrays.asList(entity))); } else { cel.add(entity); } } // Now purge the entities if necessary for (Chunk c : cem.keySet()) { List cel = cem.get(c); if (!force && cel.size() < CHUNK_ENTITY_MAX) { continue; } // Too many entities in this chunk, wipe them all for (Entity e : cel) { e.remove(); removed++; } } return removed; } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onItemSpawn(ItemSpawnEvent event) { final Item entity = event.getEntity(); new BukkitRunnable() { @Override public void run() { entity.remove(); } }.runTaskLater(plugin, ITEM_DESPAWN_RATE); } @EventHandler public void onDrop(PlayerDropItemEvent event) { enabled = ConfigEntry.AUTO_ENTITY_WIPE.getBoolean(); if (enabled) { event.setCancelled(true); } } }