Merge branch 'development'

This commit is contained in:
Brianna 2021-06-13 11:35:20 -05:00
commit f6c603e614
4 changed files with 55 additions and 51 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

14
pom.xml
View File

@ -2,7 +2,7 @@
<groupId>com.songoda</groupId> <groupId>com.songoda</groupId>
<artifactId>UltimateStacker</artifactId> <artifactId>UltimateStacker</artifactId>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>2.1.6</version> <version>2.1.7</version>
<build> <build>
<defaultGoal>clean install</defaultGoal> <defaultGoal>clean install</defaultGoal>
<finalName>UltimateStacker-${project.version}</finalName> <finalName>UltimateStacker-${project.version}</finalName>
@ -41,7 +41,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version> <version>3.3.0-SNAPSHOT</version>
<executions> <executions>
<execution> <execution>
<id>shaded</id> <id>shaded</id>
@ -94,6 +94,12 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<repositories> <repositories>
<repository> <repository>
<id>public</id> <id>public</id>
@ -112,13 +118,13 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId> <artifactId>spigot</artifactId>
<version>1.16.2</version> <version>1.17</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.songoda</groupId> <groupId>com.songoda</groupId>
<artifactId>SongodaCore</artifactId> <artifactId>SongodaCore</artifactId>
<version>2.4.55</version> <version>LATEST</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -3,6 +3,7 @@ package com.songoda.ultimatestacker.tasks;
import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion; import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.hooks.WorldGuardHook; import com.songoda.core.hooks.WorldGuardHook;
import com.songoda.core.world.SWorld;
import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.settings.Settings; import com.songoda.ultimatestacker.settings.Settings;
import com.songoda.ultimatestacker.stackable.entity.Check; import com.songoda.ultimatestacker.stackable.entity.Check;
@ -55,10 +56,16 @@ public class StackingTask extends BukkitRunnable {
onlyStackFromSpawners = Settings.ONLY_STACK_FROM_SPAWNERS.getBoolean(), onlyStackFromSpawners = Settings.ONLY_STACK_FROM_SPAWNERS.getBoolean(),
onlyStackOnSurface = Settings.ONLY_STACK_ON_SURFACE.getBoolean(); onlyStackOnSurface = Settings.ONLY_STACK_ON_SURFACE.getBoolean();
Set<SWorld> loadedWorlds = new HashSet<>();
public StackingTask(UltimateStacker plugin) { public StackingTask(UltimateStacker plugin) {
this.plugin = plugin; this.plugin = plugin;
this.stackManager = plugin.getEntityStackManager(); this.stackManager = plugin.getEntityStackManager();
// Add loaded worlds.
for (World world : Bukkit.getWorlds())
loadedWorlds.add(new SWorld(world));
// Start the stacking task. // Start the stacking task.
runTaskTimerAsynchronously(plugin, 0, Settings.STACK_SEARCH_TICK_SPEED.getInt()); runTaskTimerAsynchronously(plugin, 0, Settings.STACK_SEARCH_TICK_SPEED.getInt());
} }
@ -69,15 +76,14 @@ public class StackingTask extends BukkitRunnable {
if (!Settings.STACK_ENTITIES.getBoolean()) return; if (!Settings.STACK_ENTITIES.getBoolean()) return;
// Loop through each world. // Loop through each world.
for (World world : Bukkit.getWorlds()) { for (SWorld sWorld : loadedWorlds) {
// If world is disabled then continue to the next world. // If world is disabled then continue to the next world.
if (isWorldDisabled(sWorld.getWorld())) continue;
if (isWorldDisabled(world)) continue;
// Get the loaded entities from the current world and reverse them. // Get the loaded entities from the current world and reverse them.
List<Entity> entities; List<LivingEntity> entities;
try { try {
entities = new ArrayList<>(world.getEntities()); entities = sWorld.getLivingEntities();
} catch (Exception ignored) { } catch (Exception ignored) {
continue; continue;
// Sometimes accessing this method asynchronously throws an error. This is super rare and // 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); Collections.reverse(entities);
// Loop through the entities. // Loop through the entities.
for (Entity entity : entities) { for (LivingEntity entity : entities) {
// Get entity location to pass around as its faster this way. // Get entity location to pass around as its faster this way.
Location location = entity.getLocation(); Location location = entity.getLocation();
@ -98,12 +104,8 @@ public class StackingTask extends BukkitRunnable {
// Skip it if it has been. // Skip it if it has been.
if (this.processed.contains(entity.getUniqueId())) continue; if (this.processed.contains(entity.getUniqueId())) continue;
// Cast our entity to living entity.
LivingEntity livingEntity = (LivingEntity) entity;
// Process the entity. // Process the entity.
this.processEntity(livingEntity, location); this.processEntity(entity, sWorld, location);
} }
} }
// Clear caches in preparation for the next run. // Clear caches in preparation for the next run.
@ -118,7 +120,6 @@ public class StackingTask extends BukkitRunnable {
private boolean isEntityStackable(Entity entity) { private boolean isEntityStackable(Entity entity) {
// Make sure we have the correct entity type and that it is valid. // Make sure we have the correct entity type and that it is valid.
if (!entity.isValid() if (!entity.isValid()
|| !(entity instanceof LivingEntity)
|| entity instanceof HumanEntity || entity instanceof HumanEntity
|| entity instanceof ArmorStand || 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 // Get the stack from the entity. It should be noted that this value will
// be null if our entity is not a stack. // be null if our entity is not a stack.
EntityStack stack = plugin.getEntityStackManager().getStack(livingEntity); 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. // Get similar entities around our entity and make sure those entities are both compatible and stackable.
List<LivingEntity> stackableFriends = new LinkedList<>(); List<LivingEntity> stackableFriends = new LinkedList<>();
for (LivingEntity entity : getSimilarEntitiesAroundEntity(livingEntity, location)) { for (LivingEntity entity : getSimilarEntitiesAroundEntity(livingEntity, sWorld, location)) {
// Check to see if entity is not stackable. // Check to see if entity is not stackable.
if (!isEntityStackable(entity)) if (!isEntityStackable(entity))
continue; continue;
@ -228,7 +229,7 @@ public class StackingTask extends BukkitRunnable {
if (livingEntity.isLeashed()) if (livingEntity.isLeashed())
Bukkit.getScheduler().runTask(plugin, () -> livingEntity.getWorld() Bukkit.getScheduler().runTask(plugin, () -> livingEntity.getWorld()
.dropItemNaturally(livingEntity.getLocation(), CompatibleMaterial.LEAD.getItem())); .dropItemNaturally(livingEntity.getLocation(), CompatibleMaterial.LEAD.getItem()));
livingEntity.remove(); Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
processed.add(livingEntity.getUniqueId()); processed.add(livingEntity.getUniqueId());
return; return;
@ -246,7 +247,7 @@ public class StackingTask extends BukkitRunnable {
plugin.getDataManager().createStackedEntity(newStack, newStack.addEntityToStack(livingEntity)); plugin.getDataManager().createStackedEntity(newStack, newStack.addEntityToStack(livingEntity));
// Remove our entity and mark it as processed. // Remove our entity and mark it as processed.
livingEntity.remove(); Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
processed.add(livingEntity.getUniqueId()); processed.add(livingEntity.getUniqueId());
return; return;
} }
@ -265,8 +266,8 @@ public class StackingTask extends BukkitRunnable {
// If the stack cap is met then delete this entity. // If the stack cap is met then delete this entity.
if (maxPerTypeStacksPerChunk != -1 if (maxPerTypeStacksPerChunk != -1
&& (getSimilarStacksInChunk(livingEntity) + 1) > maxPerTypeStacksPerChunk) { && (getSimilarStacksInChunk(sWorld, livingEntity) + 1) > maxPerTypeStacksPerChunk) {
livingEntity.remove(); Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
this.processed.add(livingEntity.getUniqueId()); this.processed.add(livingEntity.getUniqueId());
return; return;
} }
@ -299,7 +300,7 @@ public class StackingTask extends BukkitRunnable {
if (entity.isLeashed()) if (entity.isLeashed())
entity.getWorld().dropItemNaturally(entity.getLocation(), CompatibleMaterial.LEAD.getItem()); entity.getWorld().dropItemNaturally(entity.getLocation(), CompatibleMaterial.LEAD.getItem());
livingEntities.add(entity); livingEntities.add(entity);
entity.remove(); Bukkit.getScheduler().runTask(plugin, entity::remove);
processed.add(entity.getUniqueId()); processed.add(entity.getUniqueId());
}); });
@ -332,17 +333,17 @@ public class StackingTask extends BukkitRunnable {
}); });
// Remove our entity and mark it as processed. // Remove our entity and mark it as processed.
livingEntity.remove(); Bukkit.getScheduler().runTask(plugin, livingEntity::remove);
processed.add(livingEntity.getUniqueId()); processed.add(livingEntity.getUniqueId());
return true; return true;
} }
private Set<CachedChunk> getNearbyChunks(Location location, double radius, boolean singleChunk) { private Set<CachedChunk> getNearbyChunks(SWorld sWorld, Location location, double radius, boolean singleChunk) {
World world = location.getWorld(); World world = location.getWorld();
Set<CachedChunk> chunks = new HashSet<>(); Set<CachedChunk> chunks = new HashSet<>();
if (world == null) return chunks; if (world == null) return chunks;
CachedChunk firstChunk = new CachedChunk(location); CachedChunk firstChunk = new CachedChunk(sWorld, location);
chunks.add(firstChunk); chunks.add(firstChunk);
if (singleChunk) return chunks; if (singleChunk) return chunks;
@ -355,15 +356,15 @@ public class StackingTask extends BukkitRunnable {
for (int x = minX; x <= maxX; ++x) { for (int x = minX; x <= maxX; ++x) {
for (int z = minZ; z <= maxZ; ++z) { for (int z = minZ; z <= maxZ; ++z) {
if (firstChunk.getX() == x && firstChunk.getZ() == z) continue; 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; return chunks;
} }
private List<LivingEntity> getNearbyEntities(Location location, double radius, boolean singleChunk) { private List<LivingEntity> getNearbyEntities(SWorld sWorld, Location location, double radius, boolean singleChunk) {
List<LivingEntity> entities = new ArrayList<>(); List<LivingEntity> entities = new ArrayList<>();
for (CachedChunk chunk : getNearbyChunks(location, radius, singleChunk)) { for (CachedChunk chunk : getNearbyChunks(sWorld, location, radius, singleChunk)) {
if (chunk == null) continue; if (chunk == null) continue;
Entity[] entityArray = new Entity[0]; Entity[] entityArray = new Entity[0];
if (cachedChunks.containsKey(chunk)) { if (cachedChunks.containsKey(chunk)) {
@ -389,20 +390,20 @@ public class StackingTask extends BukkitRunnable {
return entities; return entities;
} }
public int getSimilarStacksInChunk(LivingEntity entity) { public int getSimilarStacksInChunk(SWorld sWorld, LivingEntity entity) {
int count = 0; 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)) if (entity.getType() == e.getType() && plugin.getEntityStackManager().isStackedAndLoaded(e))
count++; count++;
} }
return count; return count;
} }
public List<LivingEntity> getSimilarEntitiesAroundEntity(LivingEntity initialEntity, Location location) { public List<LivingEntity> getSimilarEntitiesAroundEntity(LivingEntity initialEntity, SWorld sWorld, Location location) {
// Create a list of all entities around the initial entity of the same type. // Create a list of all entities around the initial entity of the same type.
List<LivingEntity> entityList = new LinkedList<>(); List<LivingEntity> 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) if (entity.getType() != initialEntity.getType() || entity == initialEntity)
continue; continue;
entityList.add(entity); entityList.add(entity);

View File

@ -1,5 +1,6 @@
package com.songoda.ultimatestacker.utils; package com.songoda.ultimatestacker.utils;
import com.songoda.core.world.SWorld;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
@ -10,65 +11,61 @@ import java.util.Objects;
public class CachedChunk { public class CachedChunk {
private final String world; private final SWorld sWorld;
private final int x; private final int x;
private final int z; private final int z;
public CachedChunk(Chunk chunk) { public CachedChunk(SWorld sWorld, Location location) {
this(chunk.getWorld().getName(), chunk.getX(), chunk.getZ()); this(sWorld, (int)location.getX() >> 4, (int)location.getZ() >> 4);
} }
public CachedChunk(Location location) { public CachedChunk(SWorld sWorld, int x, int z) {
this(location.getWorld().getName(), (int)location.getX() >> 4, (int)location.getZ() >> 4); this.sWorld = sWorld;
}
public CachedChunk(String world, int x, int z) {
this.world = world;
this.x = x; this.x = x;
this.z = z; this.z = z;
} }
public String getWorld() { public String getWorld() {
return this.world; return sWorld.getWorld().getName();
} }
public int getX() { public int getX() {
return this.x; return x;
} }
public int getZ() { public int getZ() {
return this.z; return z;
} }
public Chunk getChunk() { public Chunk getChunk() {
World world = Bukkit.getWorld(this.world); World world = sWorld.getWorld();
if (world == null) if (world == null)
return null; return null;
return world.getChunkAt(this.x, this.z); return world.getChunkAt(this.x, this.z);
} }
public Entity[] getEntities() { public Entity[] getEntities() {
if (!Bukkit.getWorld(world).isChunkLoaded(x, z)) { if (!sWorld.getWorld().isChunkLoaded(x, z)) {
return new Entity[0]; return new Entity[0];
} }
Chunk chunk = getChunk(); Chunk chunk = getChunk();
return chunk == null ? new Entity[0] : getChunk().getEntities(); return chunk == null ? new Entity[0] : sWorld.getEntitiesFromChunk(x, z);
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof Chunk) { if (o instanceof Chunk) {
Chunk other = (Chunk) o; 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) { } else if (o instanceof CachedChunk) {
CachedChunk other = (CachedChunk) o; 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; } else return false;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(this.world, this.x, this.z); return Objects.hash(getWorld(), this.x, this.z);
} }
} }