diff --git a/pom.xml b/pom.xml index 209f6f28..fe3f2279 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ org.spigotmc spigot - 1.15.1-R0.1-SNAPSHOT + 1.15.2-R0.1-SNAPSHOT provided diff --git a/src/main/java/uk/antiperson/stackmob/StackMob.java b/src/main/java/uk/antiperson/stackmob/StackMob.java index c76b2e8f..3cc3d096 100644 --- a/src/main/java/uk/antiperson/stackmob/StackMob.java +++ b/src/main/java/uk/antiperson/stackmob/StackMob.java @@ -3,15 +3,21 @@ import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; +import org.bukkit.World; import org.bukkit.command.PluginCommand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Mob; import org.bukkit.event.Listener; import org.bukkit.plugin.InvalidPluginException; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; import uk.antiperson.stackmob.commands.Commands; import uk.antiperson.stackmob.config.EntityTranslation; import uk.antiperson.stackmob.config.MainConfig; import uk.antiperson.stackmob.entity.EntityManager; +import uk.antiperson.stackmob.entity.StackEntity; import uk.antiperson.stackmob.entity.traits.TraitManager; import uk.antiperson.stackmob.hook.HookManager; import uk.antiperson.stackmob.listeners.*; @@ -24,6 +30,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; public class StackMob extends JavaPlugin { @@ -94,9 +101,61 @@ public void onEnable() { if (metrics.isEnabled()) { getLogger().info("bStats anonymous data collection has been enabled!"); } + if(getMainConfig().isAutoCheckEnabled()) + this.checkMob(); itemTools = new ItemTools(this); } + private void checkMob() + { + StackMob plugin = this; + new BukkitRunnable() { + @Override + public void run() { + AtomicInteger n = new AtomicInteger(); + for(World world:Bukkit.getWorlds()) + { + plugin.getLogger().info("Checking stack for mob in world " + world.getName()); + for (Entity entity : world.getEntities()) { + if (!(entity instanceof Mob)) { + continue; + } + LivingEntity livingEntity = (LivingEntity) entity; + plugin.getServer().getScheduler().runTask(plugin, () -> { + if (plugin.getMainConfig().isEntityBlacklisted(livingEntity)) { + return; + } + if (plugin.getEntityManager().isStackedEntity(livingEntity)) { + return; + } + StackEntity original = plugin.getEntityManager().getStackEntity(livingEntity); + Integer[] searchRadius = plugin.getMainConfig().getStackRadius(entity.getType()); + for (Entity nearbyEntity : entity.getNearbyEntities(searchRadius[0], searchRadius[1], searchRadius[2])) { + if (!(nearbyEntity instanceof Mob)) { + continue; + } + StackEntity nearby = plugin.getEntityManager().getStackEntity((LivingEntity) nearbyEntity); + if (plugin.getMainConfig().getStackThresholdEnabled(nearbyEntity.getType()) && nearby.getSize() == 1) { + continue; + } + if (!original.checkNearby(nearby)) { + continue; + } + if (nearby.merge(original)) { + return; + } + } + original.setSize(1); + plugin.getHookManager().onSpawn(original); + n.getAndIncrement(); + }); + } + } + plugin.getLogger().info(n.toString() + " entities found for stacking"); + } + }.runTaskTimer(this, 0, getMainConfig().getAutoCheckInterval()); + } + private void loadConfig() { try { getMainConfig().load(); diff --git a/src/main/java/uk/antiperson/stackmob/config/MainConfig.java b/src/main/java/uk/antiperson/stackmob/config/MainConfig.java index 143be460..21d33ae6 100644 --- a/src/main/java/uk/antiperson/stackmob/config/MainConfig.java +++ b/src/main/java/uk/antiperson/stackmob/config/MainConfig.java @@ -4,6 +4,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDamageEvent; import uk.antiperson.stackmob.StackMob; import uk.antiperson.stackmob.entity.death.DeathType; import uk.antiperson.stackmob.entity.TagMode; @@ -33,6 +34,10 @@ public Integer[] getStackRadius(EntityType type) { return getList(type, "stack.merge-range").asIntList().toArray(new Integer[2]); } + public boolean isAutoCheckEnabled(){ return getBoolean("check-task.enable"); } + + public int getAutoCheckInterval(){ return getInt("check-task.interval"); } + public int getStackInterval() { return getInt("stack.interval"); } @@ -172,6 +177,12 @@ public boolean isEntityBlacklisted(LivingEntity entity, CreatureSpawnEvent.Spawn } return isWorldBlacklisted(entity.getType(), entity.getWorld()); } + public boolean isEntityBlacklisted(LivingEntity entity) { + if (getList(entity.getType(), "types-blacklist").contains(entity.getType().toString())) { + return true; + } + return isWorldBlacklisted(entity.getType(), entity.getWorld()); + } public DeathType getDeathType(LivingEntity dead) { for (String key : getDeathSection(dead)) { @@ -187,6 +198,11 @@ public DeathType getDeathType(LivingEntity dead) { } throw new UnsupportedOperationException("Configuration error - unable to determine death type!"); } + public boolean isInstantDamage(EntityDamageEvent.DamageCause dc) + { + ConfigList configDamage = this.getList("instant-death-cause"); + return configDamage.contains(dc.name()); + } private Collection getDeathSection(LivingEntity dead) { TreeMap array = new TreeMap<>(); diff --git a/src/main/java/uk/antiperson/stackmob/entity/death/KillStepDamage.java b/src/main/java/uk/antiperson/stackmob/entity/death/KillStepDamage.java index d9a7e6f0..a8a6e9dc 100644 --- a/src/main/java/uk/antiperson/stackmob/entity/death/KillStepDamage.java +++ b/src/main/java/uk/antiperson/stackmob/entity/death/KillStepDamage.java @@ -37,6 +37,7 @@ public void onSpawn(StackEntity spawned) { } }, 5); } + spawned.getEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(maxHealth); spawned.getEntity().setHealth(maxHealth - leftOverDamage); } } diff --git a/src/main/java/uk/antiperson/stackmob/listeners/DeathListener.java b/src/main/java/uk/antiperson/stackmob/listeners/DeathListener.java index f30c9c0b..6ea23f79 100644 --- a/src/main/java/uk/antiperson/stackmob/listeners/DeathListener.java +++ b/src/main/java/uk/antiperson/stackmob/listeners/DeathListener.java @@ -12,6 +12,7 @@ import uk.antiperson.stackmob.entity.Drops; import uk.antiperson.stackmob.entity.StackEntity; import uk.antiperson.stackmob.entity.death.DeathMethod; +import uk.antiperson.stackmob.entity.death.KillAll; import java.lang.reflect.InvocationTargetException; import java.util.Map; @@ -32,7 +33,11 @@ public void onStackDeath(EntityDeathEvent event) { if (stackEntity.getSize() == 1) { return; } - DeathMethod deathMethod = calculateDeath(stackEntity); + DeathMethod deathMethod; + if(sm.getMainConfig().isInstantDamage(stackEntity.getEntity().getLastDamageCause().getCause())) + deathMethod = new KillAll(sm, stackEntity); + else + deathMethod = calculateDeath(stackEntity); int deathStep = Math.min(stackEntity.getSize(), deathMethod.calculateStep()); if (deathStep > 0 && deathStep < stackEntity.getSize()) { StackEntity spawned = stackEntity.duplicate(); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 8f73f5ff..ad6b3528 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -18,6 +18,12 @@ stack: enabled: true amount: 5 +check-task: + # Enable auto task check all entities on your map for stacking + enable: true + # Interval between each check in tick (20 Tick = 1 Second) + interval: 6000 + # Names of worlds where there should be no stacking worlds-blacklist: [] worlds-blacklist-invert: false @@ -149,6 +155,16 @@ death: reason-blacklist-invert: false type-blacklist: [] type-blacklist-invert: false +# All event instant kill mob stack (Less than default cause many bug in automatic farm) +instant-death-cause: + - BLOCK_EXPLOSION + - SUICIDE + - FALL + - FALLING_BLOCK + - CONTACT + - LAVA + - MAGIC + - SUFFOCATION # Multiply entity drops on entity death. drops: