Added /(admincmd) limitscalc <player>

This commit is contained in:
YellowZaki 2019-02-26 01:44:00 +01:00
parent 36ee63a70b
commit 28fea187b8
5 changed files with 244 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import java.util.stream.Collectors;
import org.bukkit.World;
import bentobox.addon.limits.commands.AdminCommand;
import bentobox.addon.limits.commands.LimitCalcCommand;
import bentobox.addon.limits.commands.PlayerCommand;
import bentobox.addon.limits.listeners.BlockLimitsListener;
import bentobox.addon.limits.listeners.JoinListener;
@ -45,6 +46,7 @@ public class Limits extends Addon {
{
// Register commands
gm.getAdminCommand().ifPresent(a -> new AdminCommand(this, a));
gm.getAdminCommand().ifPresent(a -> new LimitCalcCommand(this, a));
gm.getPlayerCommand().ifPresent(a -> new PlayerCommand(this, a));
log("Limits will apply to " + gm.getDescription().getName());
}

View File

@ -0,0 +1,82 @@
package bentobox.addon.limits.commands;
import bentobox.addon.limits.Limits;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
/**
*
* @author YellowZaki
*/
public class LimitCalcCommand extends CompositeCommand {
private final Limits addon;
/**
* Admin command
*
* @param addon - addon
*/
public LimitCalcCommand(Limits addon, CompositeCommand parent) {
super(parent, "limitscalc");
this.addon = addon;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#setup()
*/
@Override
public void setup() {
this.setPermission("limits.admin.limitscalc");
this.setOnlyPlayer(false);
this.setParametersHelp("admin.limitscalc.parameters");
this.setDescription("admin.limitscalc.description");
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/
@Override
public boolean execute(User user, String label, List<String> args) {
if (args.size() == 1) {
final UUID playerUUID = getPlugin().getPlayers().getUUID(args.get(0));
if (playerUUID == null) {
user.sendMessage("general.errors.unknown-player", args.get(0));
return true;
} else {
//Calculate
calcLimits(playerUUID, user);
}
return true;
} else {
showHelp(this, user);
return false;
}
}
public void calcLimits(UUID targetPlayer, User sender) {
if (getPlugin().getIslands().hasIsland(getWorld(), targetPlayer)) {
new LimitsCalc(getWorld(), getPlugin(), targetPlayer, addon, sender);
} else {
sender.sendMessage("general.errors.player-has-no-island");
}
}
@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.isEmpty()) {
// Don't show every player on the server. Require at least the first letter
return Optional.empty();
}
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
return Optional.of(Util.tabLimit(options, lastArg));
}
}

View File

@ -0,0 +1,142 @@
package bentobox.addon.limits.commands;
import bentobox.addon.limits.Limits;
import bentobox.addon.limits.listeners.BlockLimitsListener;
import bentobox.addon.limits.objects.IslandBlockCount;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.scheduler.BukkitTask;
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;
/**
*
* @author YellowZaki
*/
public class LimitsCalc {
private boolean checking;
private Limits addon;
private BentoBox instance;
private World world;
private Island island;
private BlockLimitsListener bll;
private IslandBlockCount ibc;
private Map<Material, Integer> blockCount;
private BukkitTask task;
private User sender;
LimitsCalc(World world, BentoBox instance, UUID targetPlayer, Limits addon, User sender) {
this.checking = true;
this.addon = addon;
this.instance = instance;
this.world = world;
this.island = instance.getIslands().getIsland(world, targetPlayer);
this.bll = addon.getBlockLimitListener();
this.ibc = bll.getIsland(island.getUniqueId());
blockCount = new HashMap<>();
this.sender = sender;
Set<Pair<Integer, Integer>> chunksToScan = getChunksToScan(island);
this.task = addon.getServer().getScheduler().runTaskTimer(addon.getPlugin(), () -> {
Set<ChunkSnapshot> chunkSnapshot = new HashSet<>();
if (checking) {
Iterator<Pair<Integer, Integer>> it = chunksToScan.iterator();
if (!it.hasNext()) {
// Nothing left
tidyUp();
return;
}
// Add chunk snapshots to the list
while (it.hasNext() && chunkSnapshot.size() < 200) {
Pair<Integer, Integer> pair = it.next();
if (!world.isChunkLoaded(pair.x, pair.z)) {
world.loadChunk(pair.x, pair.z);
chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
world.unloadChunk(pair.x, pair.z);
} else {
chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
}
it.remove();
}
// Move to next step
checking = false;
checkChunksAsync(chunkSnapshot);
}
}, 0L, 1);
}
private void checkChunksAsync(final Set<ChunkSnapshot> chunkSnapshot) {
// Run async task to scan chunks
addon.getServer().getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> {
for (ChunkSnapshot chunk : chunkSnapshot) {
scanChunk(chunk);
}
// Nothing happened, change state
checking = true;
});
}
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 < 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 is limited
if (bll.getLimits().containsKey(md)) {
if (!blockCount.containsKey(md)) {
blockCount.put(md, 1);
} else {
blockCount.put(md, blockCount.get(md) + 1);
}
}
}
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() {
// Cancel
task.cancel();
ibc.setBlockCount(blockCount);
bll.setIsland(island.getUniqueId(), ibc);
sender.sendMessage("admin.limitscalc.finished");
}
}

View File

@ -28,6 +28,7 @@ import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.block.BlockFromToEvent;
import bentobox.addon.limits.Limits;
import bentobox.addon.limits.objects.IslandBlockCount;
@ -122,6 +123,10 @@ public class BlockLimitsListener implements Listener {
}
return mats;
}
public Map<Material, Integer> getLimits(){
return this.defaultLimitMap;
}
/**
* Save the count database completely
@ -205,6 +210,15 @@ public class BlockLimitsListener implements Listener {
public void onBlock(EntityChangeBlockEvent e) {
process(e.getBlock(), false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlock(BlockFromToEvent e) {
if (e.getBlock().isLiquid()){
if (e.getToBlock().getType() == Material.REDSTONE_WIRE || e.getToBlock().getType() == Material.REPEATER || e.getToBlock().getType() == Material.COMPARATOR || e.getToBlock().getType() == Material.REDSTONE_TORCH) {
process(e.getToBlock(), false);
}
}
}
private int process(Block b, boolean add) {
return process(b, add, b.getType());

View File

@ -11,6 +11,10 @@ admin:
limits:
parameters: "<player>"
description: "show the island limits for player"
limitscalc:
parameters: "<player>"
description: "recalculate the island limits for player"
finished: "&aIsland recalc finished sucessfully!"
island:
limits: