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: