diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..19871eb
Binary files /dev/null and b/.DS_Store differ
diff --git a/pom.xml b/pom.xml
index 6a74a3a..d46f568 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
com.songoda
UltimateStacker
4.0.0
- 2.1.6
+ 2.1.7
clean install
UltimateStacker-${project.version}
@@ -41,7 +41,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 3.1.0
+ 3.3.0-SNAPSHOT
shaded
@@ -94,6 +94,12 @@
+
+
+ apache.snapshots
+ https://repository.apache.org/snapshots/
+
+
public
@@ -112,13 +118,13 @@
org.spigotmc
spigot
- 1.16.2
+ 1.17
provided
com.songoda
SongodaCore
- 2.4.55
+ LATEST
compile
diff --git a/src/main/java/com/songoda/ultimatestacker/tasks/StackingTask.java b/src/main/java/com/songoda/ultimatestacker/tasks/StackingTask.java
index 60e1878..f9e19f4 100644
--- a/src/main/java/com/songoda/ultimatestacker/tasks/StackingTask.java
+++ b/src/main/java/com/songoda/ultimatestacker/tasks/StackingTask.java
@@ -3,6 +3,7 @@ package com.songoda.ultimatestacker.tasks;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.hooks.WorldGuardHook;
+import com.songoda.core.world.SWorld;
import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.settings.Settings;
import com.songoda.ultimatestacker.stackable.entity.Check;
@@ -55,10 +56,16 @@ public class StackingTask extends BukkitRunnable {
onlyStackFromSpawners = Settings.ONLY_STACK_FROM_SPAWNERS.getBoolean(),
onlyStackOnSurface = Settings.ONLY_STACK_ON_SURFACE.getBoolean();
+ Set loadedWorlds = new HashSet<>();
+
public StackingTask(UltimateStacker plugin) {
this.plugin = plugin;
this.stackManager = plugin.getEntityStackManager();
+ // Add loaded worlds.
+ for (World world : Bukkit.getWorlds())
+ loadedWorlds.add(new SWorld(world));
+
// Start the stacking task.
runTaskTimerAsynchronously(plugin, 0, Settings.STACK_SEARCH_TICK_SPEED.getInt());
}
@@ -69,15 +76,14 @@ public class StackingTask extends BukkitRunnable {
if (!Settings.STACK_ENTITIES.getBoolean()) return;
// Loop through each world.
- for (World world : Bukkit.getWorlds()) {
+ for (SWorld sWorld : loadedWorlds) {
// If world is disabled then continue to the next world.
-
- if (isWorldDisabled(world)) continue;
+ if (isWorldDisabled(sWorld.getWorld())) continue;
// Get the loaded entities from the current world and reverse them.
- List entities;
+ List entities;
try {
- entities = new ArrayList<>(world.getEntities());
+ entities = sWorld.getLivingEntities();
} catch (Exception ignored) {
continue;
// Sometimes accessing this method asynchronously throws an error. This is super rare and
@@ -86,7 +92,7 @@ public class StackingTask extends BukkitRunnable {
Collections.reverse(entities);
// Loop through the entities.
- for (Entity entity : entities) {
+ for (LivingEntity entity : entities) {
// Get entity location to pass around as its faster this way.
Location location = entity.getLocation();
@@ -98,12 +104,8 @@ public class StackingTask extends BukkitRunnable {
// Skip it if it has been.
if (this.processed.contains(entity.getUniqueId())) continue;
- // Cast our entity to living entity.
- LivingEntity livingEntity = (LivingEntity) entity;
-
// Process the entity.
- this.processEntity(livingEntity, location);
-
+ this.processEntity(entity, sWorld, location);
}
}
// Clear caches in preparation for the next run.
@@ -118,7 +120,6 @@ public class StackingTask extends BukkitRunnable {
private boolean isEntityStackable(Entity entity) {
// Make sure we have the correct entity type and that it is valid.
if (!entity.isValid()
- || !(entity instanceof LivingEntity)
|| entity instanceof HumanEntity
|| entity instanceof ArmorStand
@@ -154,7 +155,7 @@ public class StackingTask extends BukkitRunnable {
}
- private void processEntity(LivingEntity livingEntity, Location location) {
+ private void processEntity(LivingEntity livingEntity, SWorld sWorld, Location location) {
// Get the stack from the entity. It should be noted that this value will
// be null if our entity is not a stack.
EntityStack stack = plugin.getEntityStackManager().getStack(livingEntity);
@@ -179,7 +180,7 @@ public class StackingTask extends BukkitRunnable {
// Get similar entities around our entity and make sure those entities are both compatible and stackable.
List stackableFriends = new LinkedList<>();
- for (LivingEntity entity : getSimilarEntitiesAroundEntity(livingEntity, location)) {
+ for (LivingEntity entity : getSimilarEntitiesAroundEntity(livingEntity, sWorld, location)) {
// Check to see if entity is not stackable.
if (!isEntityStackable(entity))
continue;
@@ -228,7 +229,7 @@ public class StackingTask extends BukkitRunnable {
if (livingEntity.isLeashed())
Bukkit.getScheduler().runTask(plugin, () -> livingEntity.getWorld()
.dropItemNaturally(livingEntity.getLocation(), CompatibleMaterial.LEAD.getItem()));
- livingEntity.remove();
+ Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
processed.add(livingEntity.getUniqueId());
return;
@@ -246,7 +247,7 @@ public class StackingTask extends BukkitRunnable {
plugin.getDataManager().createStackedEntity(newStack, newStack.addEntityToStack(livingEntity));
// Remove our entity and mark it as processed.
- livingEntity.remove();
+ Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
processed.add(livingEntity.getUniqueId());
return;
}
@@ -265,8 +266,8 @@ public class StackingTask extends BukkitRunnable {
// If the stack cap is met then delete this entity.
if (maxPerTypeStacksPerChunk != -1
- && (getSimilarStacksInChunk(livingEntity) + 1) > maxPerTypeStacksPerChunk) {
- livingEntity.remove();
+ && (getSimilarStacksInChunk(sWorld, livingEntity) + 1) > maxPerTypeStacksPerChunk) {
+ Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
this.processed.add(livingEntity.getUniqueId());
return;
}
@@ -299,7 +300,7 @@ public class StackingTask extends BukkitRunnable {
if (entity.isLeashed())
entity.getWorld().dropItemNaturally(entity.getLocation(), CompatibleMaterial.LEAD.getItem());
livingEntities.add(entity);
- entity.remove();
+ Bukkit.getScheduler().runTask(plugin, entity::remove);
processed.add(entity.getUniqueId());
});
@@ -332,17 +333,17 @@ public class StackingTask extends BukkitRunnable {
});
// Remove our entity and mark it as processed.
- livingEntity.remove();
+ Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
processed.add(livingEntity.getUniqueId());
return true;
}
- private Set getNearbyChunks(Location location, double radius, boolean singleChunk) {
+ private Set getNearbyChunks(SWorld sWorld, Location location, double radius, boolean singleChunk) {
World world = location.getWorld();
Set chunks = new HashSet<>();
if (world == null) return chunks;
- CachedChunk firstChunk = new CachedChunk(location);
+ CachedChunk firstChunk = new CachedChunk(sWorld, location);
chunks.add(firstChunk);
if (singleChunk) return chunks;
@@ -355,15 +356,15 @@ public class StackingTask extends BukkitRunnable {
for (int x = minX; x <= maxX; ++x) {
for (int z = minZ; z <= maxZ; ++z) {
if (firstChunk.getX() == x && firstChunk.getZ() == z) continue;
- chunks.add(new CachedChunk(world.getName(), x, z));
+ chunks.add(new CachedChunk(sWorld, x, z));
}
}
return chunks;
}
- private List getNearbyEntities(Location location, double radius, boolean singleChunk) {
+ private List getNearbyEntities(SWorld sWorld, Location location, double radius, boolean singleChunk) {
List entities = new ArrayList<>();
- for (CachedChunk chunk : getNearbyChunks(location, radius, singleChunk)) {
+ for (CachedChunk chunk : getNearbyChunks(sWorld, location, radius, singleChunk)) {
if (chunk == null) continue;
Entity[] entityArray = new Entity[0];
if (cachedChunks.containsKey(chunk)) {
@@ -389,20 +390,20 @@ public class StackingTask extends BukkitRunnable {
return entities;
}
- public int getSimilarStacksInChunk(LivingEntity entity) {
+ public int getSimilarStacksInChunk(SWorld sWorld, LivingEntity entity) {
int count = 0;
- for (LivingEntity e : getNearbyEntities(entity.getLocation(), -1, true)) {
+ for (LivingEntity e : getNearbyEntities(sWorld, entity.getLocation(), -1, true)) {
if (entity.getType() == e.getType() && plugin.getEntityStackManager().isStackedAndLoaded(e))
count++;
}
return count;
}
- public List getSimilarEntitiesAroundEntity(LivingEntity initialEntity, Location location) {
+ public List getSimilarEntitiesAroundEntity(LivingEntity initialEntity, SWorld sWorld, Location location) {
// Create a list of all entities around the initial entity of the same type.
List entityList = new LinkedList<>();
- for (LivingEntity entity : getNearbyEntities(location, searchRadius, stackWholeChunk)) {
+ for (LivingEntity entity : getNearbyEntities(sWorld, location, searchRadius, stackWholeChunk)) {
if (entity.getType() != initialEntity.getType() || entity == initialEntity)
continue;
entityList.add(entity);
diff --git a/src/main/java/com/songoda/ultimatestacker/utils/CachedChunk.java b/src/main/java/com/songoda/ultimatestacker/utils/CachedChunk.java
index f6d8d2b..ad3ec47 100644
--- a/src/main/java/com/songoda/ultimatestacker/utils/CachedChunk.java
+++ b/src/main/java/com/songoda/ultimatestacker/utils/CachedChunk.java
@@ -1,5 +1,6 @@
package com.songoda.ultimatestacker.utils;
+import com.songoda.core.world.SWorld;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
@@ -10,65 +11,61 @@ import java.util.Objects;
public class CachedChunk {
- private final String world;
+ private final SWorld sWorld;
private final int x;
private final int z;
- public CachedChunk(Chunk chunk) {
- this(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
+ public CachedChunk(SWorld sWorld, Location location) {
+ this(sWorld, (int)location.getX() >> 4, (int)location.getZ() >> 4);
}
- public CachedChunk(Location location) {
- this(location.getWorld().getName(), (int)location.getX() >> 4, (int)location.getZ() >> 4);
- }
-
- public CachedChunk(String world, int x, int z) {
- this.world = world;
+ public CachedChunk(SWorld sWorld, int x, int z) {
+ this.sWorld = sWorld;
this.x = x;
this.z = z;
}
public String getWorld() {
- return this.world;
+ return sWorld.getWorld().getName();
}
public int getX() {
- return this.x;
+ return x;
}
public int getZ() {
- return this.z;
+ return z;
}
public Chunk getChunk() {
- World world = Bukkit.getWorld(this.world);
+ World world = sWorld.getWorld();
if (world == null)
return null;
return world.getChunkAt(this.x, this.z);
}
public Entity[] getEntities() {
- if (!Bukkit.getWorld(world).isChunkLoaded(x, z)) {
+ if (!sWorld.getWorld().isChunkLoaded(x, z)) {
return new Entity[0];
}
Chunk chunk = getChunk();
- return chunk == null ? new Entity[0] : getChunk().getEntities();
+ return chunk == null ? new Entity[0] : sWorld.getEntitiesFromChunk(x, z);
}
@Override
public boolean equals(Object o) {
if (o instanceof Chunk) {
Chunk other = (Chunk) o;
- return this.world.equals(other.getWorld().getName()) && this.x == other.getX() && this.z == other.getZ();
+ return getWorld().equals(other.getWorld().getName()) && this.x == other.getX() && this.z == other.getZ();
} else if (o instanceof CachedChunk) {
CachedChunk other = (CachedChunk) o;
- return this.world.equals(other.getWorld()) && this.x == other.getX() && this.z == other.getZ();
+ return getWorld().equals(other.getWorld()) && this.x == other.getX() && this.z == other.getZ();
} else return false;
}
@Override
public int hashCode() {
- return Objects.hash(this.world, this.x, this.z);
+ return Objects.hash(getWorld(), this.x, this.z);
}
}