121 lines
4.6 KiB
Java
121 lines
4.6 KiB
Java
package bentobox.addon.limits.commands;
|
|
|
|
import java.util.*;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.stream.Collectors;
|
|
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.ChunkSnapshot;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.World;
|
|
|
|
import bentobox.addon.limits.Limits;
|
|
import bentobox.addon.limits.listeners.BlockLimitsListener;
|
|
import bentobox.addon.limits.objects.IslandBlockCount;
|
|
import world.bentobox.bentobox.BentoBox;
|
|
import world.bentobox.bentobox.api.user.User;
|
|
import world.bentobox.bentobox.database.objects.Island;
|
|
import world.bentobox.bentobox.util.Pair;
|
|
import world.bentobox.bentobox.util.Util;
|
|
|
|
/**
|
|
*
|
|
* @author YellowZaki, tastybento
|
|
*/
|
|
public class LimitsCalc {
|
|
|
|
private final Limits addon;
|
|
private final World world;
|
|
private final Island island;
|
|
private final BlockLimitsListener bll;
|
|
private IslandBlockCount ibc;
|
|
private final Map<Material, AtomicInteger> blockCount;
|
|
private final User sender;
|
|
private final Set<Pair<Integer, Integer>> chunksToScan;
|
|
private int count;
|
|
|
|
|
|
LimitsCalc(World world, BentoBox instance, UUID targetPlayer, Limits addon, User sender) {
|
|
this.addon = addon;
|
|
this.island = instance.getIslands().getIsland(world, targetPlayer);
|
|
this.bll = addon.getBlockLimitListener();
|
|
this.ibc = bll.getIsland(island.getUniqueId());
|
|
blockCount = new EnumMap<>(Material.class);
|
|
this.sender = sender;
|
|
this.world = world;
|
|
|
|
// Get chunks to scan
|
|
chunksToScan = getChunksToScan(island);
|
|
count = 0;
|
|
chunksToScan.forEach(c -> Util.getChunkAtAsync(world, c.x, c.z).thenAccept(ch -> {
|
|
ChunkSnapshot snapShot = ch.getChunkSnapshot();
|
|
Bukkit.getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> {
|
|
this.scanChunk(snapShot);
|
|
count++;
|
|
if (count == chunksToScan.size()) {
|
|
this.tidyUp();
|
|
}
|
|
});
|
|
}));
|
|
|
|
}
|
|
|
|
private void scanChunk(ChunkSnapshot chunk) {
|
|
for (int x = 0; x < 16; x++) {
|
|
// Check if the block coordinate is inside the protection zone and if not, don't count it
|
|
if (chunk.getX() * 16 + x < island.getMinProtectedX() || chunk.getX() * 16 + x >= island.getMinProtectedX() + island.getProtectionRange() * 2) {
|
|
continue;
|
|
}
|
|
for (int z = 0; z < 16; z++) {
|
|
// Check if the block coordinate is inside the protection zone and if not, don't count it
|
|
if (chunk.getZ() * 16 + z < island.getMinProtectedZ() || chunk.getZ() * 16 + z >= island.getMinProtectedZ() + island.getProtectionRange() * 2) {
|
|
continue;
|
|
}
|
|
for (int y = 0; y < Objects.requireNonNull(island.getCenter().getWorld()).getMaxHeight(); y++) {
|
|
Material blockData = chunk.getBlockType(x, y, z);
|
|
// Air is free
|
|
if (!blockData.equals(Material.AIR)) {
|
|
checkBlock(blockData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void checkBlock(Material md) {
|
|
md = bll.fixMaterial(md);
|
|
// md is limited
|
|
if (bll.getMaterialLimits(world, island.getUniqueId()).containsKey(md)) {
|
|
if (!blockCount.containsKey(md)) {
|
|
blockCount.put(md, new AtomicInteger(1));
|
|
} else {
|
|
blockCount.get(md).getAndIncrement();
|
|
}
|
|
}
|
|
}
|
|
|
|
private Set<Pair<Integer, Integer>> getChunksToScan(Island island) {
|
|
Set<Pair<Integer, Integer>> chunkSnapshot = new HashSet<>();
|
|
for (int x = island.getMinProtectedX(); x < (island.getMinProtectedX() + island.getProtectionRange() * 2 + 16); x += 16) {
|
|
for (int z = island.getMinProtectedZ(); z < (island.getMinProtectedZ() + island.getProtectionRange() * 2 + 16); z += 16) {
|
|
Pair<Integer, Integer> pair = new Pair<>(world.getBlockAt(x, 0, z).getChunk().getX(), world.getBlockAt(x, 0, z).getChunk().getZ());
|
|
chunkSnapshot.add(pair);
|
|
}
|
|
}
|
|
return chunkSnapshot;
|
|
}
|
|
|
|
private void tidyUp() {
|
|
if (ibc == null) {
|
|
ibc = new IslandBlockCount();
|
|
}
|
|
ibc.setBlockCount(blockCount.entrySet().stream()
|
|
.collect(Collectors.toMap(
|
|
Map.Entry::getKey,
|
|
entry -> entry.getValue().get())));
|
|
bll.setIsland(island.getUniqueId(), ibc);
|
|
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> sender.sendMessage("admin.limits.calc.finished"));
|
|
}
|
|
|
|
}
|