mirror of
https://github.com/BentoBoxWorld/Level.git
synced 2024-11-23 18:45:17 +01:00
Isolate UltimateStacker imports so no errors if US is not installed (#307)
Fixes #306
This commit is contained in:
parent
1bd6219f94
commit
a4f8d12138
@ -40,8 +40,6 @@ import com.bgsoftware.wildstacker.api.objects.StackedBarrel;
|
|||||||
import com.google.common.collect.Multiset;
|
import com.google.common.collect.Multiset;
|
||||||
import com.google.common.collect.Multiset.Entry;
|
import com.google.common.collect.Multiset.Entry;
|
||||||
import com.google.common.collect.Multisets;
|
import com.google.common.collect.Multisets;
|
||||||
import com.craftaro.ultimatestacker.api.UltimateStackerApi;
|
|
||||||
import com.craftaro.ultimatestacker.api.utils.Stackable;
|
|
||||||
|
|
||||||
import dev.rosewood.rosestacker.api.RoseStackerAPI;
|
import dev.rosewood.rosestacker.api.RoseStackerAPI;
|
||||||
import us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI;
|
import us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI;
|
||||||
@ -58,13 +56,13 @@ public class IslandLevelCalculator {
|
|||||||
private static final String LINE_BREAK = "==================================";
|
private static final String LINE_BREAK = "==================================";
|
||||||
public static final long MAX_AMOUNT = 10000000;
|
public static final long MAX_AMOUNT = 10000000;
|
||||||
private static final List<Material> CHESTS = Arrays.asList(Material.CHEST, Material.CHEST_MINECART,
|
private static final List<Material> CHESTS = Arrays.asList(Material.CHEST, Material.CHEST_MINECART,
|
||||||
Material.TRAPPED_CHEST, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX,
|
Material.TRAPPED_CHEST, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX,
|
||||||
Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX,
|
Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX,
|
||||||
Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX,
|
Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX,
|
||||||
Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX,
|
Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX,
|
||||||
Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.RED_SHULKER_BOX,
|
Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.RED_SHULKER_BOX,
|
||||||
Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX, Material.COMPOSTER, Material.BARREL,
|
Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX, Material.COMPOSTER, Material.BARREL,
|
||||||
Material.DISPENSER, Material.DROPPER, Material.SMOKER, Material.BLAST_FURNACE);
|
Material.DISPENSER, Material.DROPPER, Material.SMOKER, Material.BLAST_FURNACE);
|
||||||
private static final int CHUNKS_TO_SCAN = 100;
|
private static final int CHUNKS_TO_SCAN = 100;
|
||||||
private final Level addon;
|
private final Level addon;
|
||||||
private final Queue<Pair<Integer, Integer>> chunksToCheck;
|
private final Queue<Pair<Integer, Integer>> chunksToCheck;
|
||||||
@ -91,34 +89,34 @@ public class IslandLevelCalculator {
|
|||||||
* @param zeroIsland - true if the calculation is due to an island zeroing
|
* @param zeroIsland - true if the calculation is due to an island zeroing
|
||||||
*/
|
*/
|
||||||
public IslandLevelCalculator(Level addon, Island island, CompletableFuture<Results> r, boolean zeroIsland) {
|
public IslandLevelCalculator(Level addon, Island island, CompletableFuture<Results> r, boolean zeroIsland) {
|
||||||
this.addon = addon;
|
this.addon = addon;
|
||||||
this.island = island;
|
this.island = island;
|
||||||
this.r = r;
|
this.r = r;
|
||||||
this.zeroIsland = zeroIsland;
|
this.zeroIsland = zeroIsland;
|
||||||
results = new Results();
|
results = new Results();
|
||||||
duration = System.currentTimeMillis();
|
duration = System.currentTimeMillis();
|
||||||
chunksToCheck = getChunksToScan(island);
|
chunksToCheck = getChunksToScan(island);
|
||||||
this.limitCount = new EnumMap<>(addon.getBlockConfig().getBlockLimits());
|
this.limitCount = new EnumMap<>(addon.getBlockConfig().getBlockLimits());
|
||||||
// Get the initial island level
|
// Get the initial island level
|
||||||
results.initialLevel.set(addon.getInitialIslandLevel(island));
|
results.initialLevel.set(addon.getInitialIslandLevel(island));
|
||||||
// Set up the worlds
|
// Set up the worlds
|
||||||
worlds.put(Environment.NORMAL, Util.getWorld(island.getWorld()));
|
worlds.put(Environment.NORMAL, Util.getWorld(island.getWorld()));
|
||||||
// Nether
|
// Nether
|
||||||
if (addon.getSettings().isNether()) {
|
if (addon.getSettings().isNether()) {
|
||||||
World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld());
|
World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld());
|
||||||
if (nether != null) {
|
if (nether != null) {
|
||||||
worlds.put(Environment.NETHER, nether);
|
worlds.put(Environment.NETHER, nether);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// End
|
// End
|
||||||
if (addon.getSettings().isEnd()) {
|
if (addon.getSettings().isEnd()) {
|
||||||
World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld());
|
World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld());
|
||||||
if (end != null) {
|
if (end != null) {
|
||||||
worlds.put(Environment.THE_END, end);
|
worlds.put(Environment.THE_END, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sea Height
|
// Sea Height
|
||||||
seaHeight = addon.getPlugin().getIWM().getSeaHeight(island.getWorld());
|
seaHeight = addon.getPlugin().getIWM().getSeaHeight(island.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,18 +126,18 @@ public class IslandLevelCalculator {
|
|||||||
* @return level of island
|
* @return level of island
|
||||||
*/
|
*/
|
||||||
private long calculateLevel(long blockAndDeathPoints) {
|
private long calculateLevel(long blockAndDeathPoints) {
|
||||||
String calcString = addon.getSettings().getLevelCalc();
|
String calcString = addon.getSettings().getLevelCalc();
|
||||||
String withValues = calcString.replace("blocks", String.valueOf(blockAndDeathPoints)).replace("level_cost",
|
String withValues = calcString.replace("blocks", String.valueOf(blockAndDeathPoints)).replace("level_cost",
|
||||||
String.valueOf(this.addon.getSettings().getLevelCost()));
|
String.valueOf(this.addon.getSettings().getLevelCost()));
|
||||||
long evalWithValues;
|
long evalWithValues;
|
||||||
try {
|
try {
|
||||||
evalWithValues = (long) EquationEvaluator.eval(withValues);
|
evalWithValues = (long) EquationEvaluator.eval(withValues);
|
||||||
return evalWithValues - (addon.getSettings().isZeroNewIslandLevels() ? results.initialLevel.get() : 0);
|
return evalWithValues - (addon.getSettings().isZeroNewIslandLevels() ? results.initialLevel.get() : 0);
|
||||||
|
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
addon.getPlugin().logStacktrace(e);
|
addon.getPlugin().logStacktrace(e);
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,14 +148,14 @@ public class IslandLevelCalculator {
|
|||||||
* @param belowSeaLevel - true if below sea level
|
* @param belowSeaLevel - true if below sea level
|
||||||
*/
|
*/
|
||||||
private void checkBlock(Material mat, boolean belowSeaLevel) {
|
private void checkBlock(Material mat, boolean belowSeaLevel) {
|
||||||
int count = limitCount(mat);
|
int count = limitCount(mat);
|
||||||
if (belowSeaLevel) {
|
if (belowSeaLevel) {
|
||||||
results.underWaterBlockCount.addAndGet(count);
|
results.underWaterBlockCount.addAndGet(count);
|
||||||
results.uwCount.add(mat);
|
results.uwCount.add(mat);
|
||||||
} else {
|
} else {
|
||||||
results.rawBlockCount.addAndGet(count);
|
results.rawBlockCount.addAndGet(count);
|
||||||
results.mdCount.add(mat);
|
results.mdCount.add(mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,22 +165,22 @@ public class IslandLevelCalculator {
|
|||||||
* @return - set of pairs of x,z coordinates to check
|
* @return - set of pairs of x,z coordinates to check
|
||||||
*/
|
*/
|
||||||
private Queue<Pair<Integer, Integer>> getChunksToScan(Island island) {
|
private Queue<Pair<Integer, Integer>> getChunksToScan(Island island) {
|
||||||
Queue<Pair<Integer, Integer>> chunkQueue = new ConcurrentLinkedQueue<>();
|
Queue<Pair<Integer, Integer>> chunkQueue = new ConcurrentLinkedQueue<>();
|
||||||
for (int x = island.getMinProtectedX(); x < (island.getMinProtectedX() + island.getProtectionRange() * 2
|
for (int x = island.getMinProtectedX(); x < (island.getMinProtectedX() + island.getProtectionRange() * 2
|
||||||
+ 16); x += 16) {
|
+ 16); x += 16) {
|
||||||
for (int z = island.getMinProtectedZ(); z < (island.getMinProtectedZ() + island.getProtectionRange() * 2
|
for (int z = island.getMinProtectedZ(); z < (island.getMinProtectedZ() + island.getProtectionRange() * 2
|
||||||
+ 16); z += 16) {
|
+ 16); z += 16) {
|
||||||
chunkQueue.add(new Pair<>(x >> 4, z >> 4));
|
chunkQueue.add(new Pair<>(x >> 4, z >> 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return chunkQueue;
|
return chunkQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the island
|
* @return the island
|
||||||
*/
|
*/
|
||||||
public Island getIsland() {
|
public Island getIsland() {
|
||||||
return island;
|
return island;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,7 +189,7 @@ public class IslandLevelCalculator {
|
|||||||
* @return the r
|
* @return the r
|
||||||
*/
|
*/
|
||||||
public CompletableFuture<Results> getR() {
|
public CompletableFuture<Results> getR() {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,67 +198,67 @@ public class IslandLevelCalculator {
|
|||||||
* @return a list of lines
|
* @return a list of lines
|
||||||
*/
|
*/
|
||||||
private List<String> getReport() {
|
private List<String> getReport() {
|
||||||
List<String> reportLines = new ArrayList<>();
|
List<String> reportLines = new ArrayList<>();
|
||||||
// provide counts
|
// provide counts
|
||||||
reportLines.add("Level Log for island in " + addon.getPlugin().getIWM().getFriendlyName(island.getWorld())
|
reportLines.add("Level Log for island in " + addon.getPlugin().getIWM().getFriendlyName(island.getWorld())
|
||||||
+ " at " + Util.xyz(island.getCenter().toVector()));
|
+ " at " + Util.xyz(island.getCenter().toVector()));
|
||||||
reportLines.add("Island owner UUID = " + island.getOwner());
|
reportLines.add("Island owner UUID = " + island.getOwner());
|
||||||
reportLines.add("Total block value count = " + String.format("%,d", results.rawBlockCount.get()));
|
reportLines.add("Total block value count = " + String.format("%,d", results.rawBlockCount.get()));
|
||||||
reportLines.add("Formula to calculate island level: " + addon.getSettings().getLevelCalc());
|
reportLines.add("Formula to calculate island level: " + addon.getSettings().getLevelCalc());
|
||||||
reportLines.add("Level cost = " + addon.getSettings().getLevelCost());
|
reportLines.add("Level cost = " + addon.getSettings().getLevelCost());
|
||||||
reportLines.add("Deaths handicap = " + results.deathHandicap.get());
|
reportLines.add("Deaths handicap = " + results.deathHandicap.get());
|
||||||
if (addon.getSettings().isZeroNewIslandLevels()) {
|
if (addon.getSettings().isZeroNewIslandLevels()) {
|
||||||
reportLines.add("Initial island level = " + (0L - addon.getManager().getInitialLevel(island)));
|
reportLines.add("Initial island level = " + (0L - addon.getManager().getInitialLevel(island)));
|
||||||
}
|
}
|
||||||
reportLines.add("Previous level = " + addon.getManager().getIslandLevel(island.getWorld(), island.getOwner()));
|
reportLines.add("Previous level = " + addon.getManager().getIslandLevel(island.getWorld(), island.getOwner()));
|
||||||
reportLines.add("New level = " + results.getLevel());
|
reportLines.add("New level = " + results.getLevel());
|
||||||
reportLines.add(LINE_BREAK);
|
reportLines.add(LINE_BREAK);
|
||||||
int total = 0;
|
int total = 0;
|
||||||
if (!results.uwCount.isEmpty()) {
|
if (!results.uwCount.isEmpty()) {
|
||||||
reportLines.add("Underwater block count (Multiplier = x" + addon.getSettings().getUnderWaterMultiplier()
|
reportLines.add("Underwater block count (Multiplier = x" + addon.getSettings().getUnderWaterMultiplier()
|
||||||
+ ") value");
|
+ ") value");
|
||||||
reportLines.add("Total number of underwater blocks = " + String.format("%,d", results.uwCount.size()));
|
reportLines.add("Total number of underwater blocks = " + String.format("%,d", results.uwCount.size()));
|
||||||
reportLines.addAll(sortedReport(total, results.uwCount));
|
reportLines.addAll(sortedReport(total, results.uwCount));
|
||||||
}
|
}
|
||||||
reportLines.add("Regular block count");
|
reportLines.add("Regular block count");
|
||||||
reportLines.add("Total number of blocks = " + String.format("%,d", results.mdCount.size()));
|
reportLines.add("Total number of blocks = " + String.format("%,d", results.mdCount.size()));
|
||||||
reportLines.addAll(sortedReport(total, results.mdCount));
|
reportLines.addAll(sortedReport(total, results.mdCount));
|
||||||
|
|
||||||
reportLines.add(
|
reportLines.add(
|
||||||
"Blocks not counted because they exceeded limits: " + String.format("%,d", results.ofCount.size()));
|
"Blocks not counted because they exceeded limits: " + String.format("%,d", results.ofCount.size()));
|
||||||
Iterable<Multiset.Entry<Material>> entriesSortedByCount = results.ofCount.entrySet();
|
Iterable<Multiset.Entry<Material>> entriesSortedByCount = results.ofCount.entrySet();
|
||||||
Iterator<Entry<Material>> it = entriesSortedByCount.iterator();
|
Iterator<Entry<Material>> it = entriesSortedByCount.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Entry<Material> type = it.next();
|
Entry<Material> type = it.next();
|
||||||
Integer limit = addon.getBlockConfig().getBlockLimits().get(type.getElement());
|
Integer limit = addon.getBlockConfig().getBlockLimits().get(type.getElement());
|
||||||
String explain = ")";
|
String explain = ")";
|
||||||
if (limit == null) {
|
if (limit == null) {
|
||||||
Material generic = type.getElement();
|
Material generic = type.getElement();
|
||||||
limit = addon.getBlockConfig().getBlockLimits().get(generic);
|
limit = addon.getBlockConfig().getBlockLimits().get(generic);
|
||||||
explain = " - All types)";
|
explain = " - All types)";
|
||||||
}
|
}
|
||||||
reportLines.add(type.getElement().toString() + ": " + String.format("%,d", type.getCount())
|
reportLines.add(type.getElement().toString() + ": " + String.format("%,d", type.getCount())
|
||||||
+ " blocks (max " + limit + explain);
|
+ " blocks (max " + limit + explain);
|
||||||
}
|
}
|
||||||
reportLines.add(LINE_BREAK);
|
reportLines.add(LINE_BREAK);
|
||||||
reportLines.add("Blocks on island that are not in config.yml");
|
reportLines.add("Blocks on island that are not in config.yml");
|
||||||
reportLines.add("Total number = " + String.format("%,d", results.ncCount.size()));
|
reportLines.add("Total number = " + String.format("%,d", results.ncCount.size()));
|
||||||
entriesSortedByCount = results.ncCount.entrySet();
|
entriesSortedByCount = results.ncCount.entrySet();
|
||||||
it = entriesSortedByCount.iterator();
|
it = entriesSortedByCount.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Entry<Material> type = it.next();
|
Entry<Material> type = it.next();
|
||||||
reportLines.add(type.getElement().toString() + ": " + String.format("%,d", type.getCount()) + " blocks");
|
reportLines.add(type.getElement().toString() + ": " + String.format("%,d", type.getCount()) + " blocks");
|
||||||
}
|
}
|
||||||
reportLines.add(LINE_BREAK);
|
reportLines.add(LINE_BREAK);
|
||||||
|
|
||||||
return reportLines;
|
return reportLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the results
|
* @return the results
|
||||||
*/
|
*/
|
||||||
public Results getResults() {
|
public Results getResults() {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,13 +268,13 @@ public class IslandLevelCalculator {
|
|||||||
* @return value of a material
|
* @return value of a material
|
||||||
*/
|
*/
|
||||||
private int getValue(Material md) {
|
private int getValue(Material md) {
|
||||||
Integer value = addon.getBlockConfig().getValue(island.getWorld(), md);
|
Integer value = addon.getBlockConfig().getValue(island.getWorld(), md);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
// Not in config
|
// Not in config
|
||||||
results.ncCount.add(md);
|
results.ncCount.add(md);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,44 +286,44 @@ public class IslandLevelCalculator {
|
|||||||
* there is no island nether
|
* there is no island nether
|
||||||
*/
|
*/
|
||||||
private CompletableFuture<List<Chunk>> getWorldChunk(Environment env, Queue<Pair<Integer, Integer>> pairList) {
|
private CompletableFuture<List<Chunk>> getWorldChunk(Environment env, Queue<Pair<Integer, Integer>> pairList) {
|
||||||
if (worlds.containsKey(env)) {
|
if (worlds.containsKey(env)) {
|
||||||
CompletableFuture<List<Chunk>> r2 = new CompletableFuture<>();
|
CompletableFuture<List<Chunk>> r2 = new CompletableFuture<>();
|
||||||
List<Chunk> chunkList = new ArrayList<>();
|
List<Chunk> chunkList = new ArrayList<>();
|
||||||
World world = worlds.get(env);
|
World world = worlds.get(env);
|
||||||
// Get the chunk, and then coincidentally check the RoseStacker
|
// Get the chunk, and then coincidentally check the RoseStacker
|
||||||
loadChunks(r2, world, pairList, chunkList);
|
loadChunks(r2, world, pairList, chunkList);
|
||||||
return r2;
|
return r2;
|
||||||
}
|
}
|
||||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadChunks(CompletableFuture<List<Chunk>> r2, World world, Queue<Pair<Integer, Integer>> pairList,
|
private void loadChunks(CompletableFuture<List<Chunk>> r2, World world, Queue<Pair<Integer, Integer>> pairList,
|
||||||
List<Chunk> chunkList) {
|
List<Chunk> chunkList) {
|
||||||
if (pairList.isEmpty()) {
|
if (pairList.isEmpty()) {
|
||||||
r2.complete(chunkList);
|
r2.complete(chunkList);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Pair<Integer, Integer> p = pairList.poll();
|
Pair<Integer, Integer> p = pairList.poll();
|
||||||
Util.getChunkAtAsync(world, p.x, p.z, world.getEnvironment().equals(Environment.NETHER)).thenAccept(chunk -> {
|
Util.getChunkAtAsync(world, p.x, p.z, world.getEnvironment().equals(Environment.NETHER)).thenAccept(chunk -> {
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
chunkList.add(chunk);
|
chunkList.add(chunk);
|
||||||
roseStackerCheck(chunk);
|
roseStackerCheck(chunk);
|
||||||
}
|
}
|
||||||
loadChunks(r2, world, pairList, chunkList); // Iteration
|
loadChunks(r2, world, pairList, chunkList); // Iteration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void roseStackerCheck(Chunk chunk) {
|
private void roseStackerCheck(Chunk chunk) {
|
||||||
if (addon.isRoseStackersEnabled()) {
|
if (addon.isRoseStackersEnabled()) {
|
||||||
RoseStackerAPI.getInstance().getStackedBlocks(Collections.singletonList(chunk)).forEach(e -> {
|
RoseStackerAPI.getInstance().getStackedBlocks(Collections.singletonList(chunk)).forEach(e -> {
|
||||||
// Blocks below sea level can be scored differently
|
// Blocks below sea level can be scored differently
|
||||||
boolean belowSeaLevel = seaHeight > 0 && e.getLocation().getY() <= seaHeight;
|
boolean belowSeaLevel = seaHeight > 0 && e.getLocation().getY() <= seaHeight;
|
||||||
// Check block once because the base block will be counted in the chunk snapshot
|
// Check block once because the base block will be counted in the chunk snapshot
|
||||||
for (int _x = 0; _x < e.getStackSize() - 1; _x++) {
|
for (int _x = 0; _x < e.getStackSize() - 1; _x++) {
|
||||||
checkBlock(e.getBlock().getType(), belowSeaLevel);
|
checkBlock(e.getBlock().getType(), belowSeaLevel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,17 +334,17 @@ public class IslandLevelCalculator {
|
|||||||
* @return value of the block if can be counted
|
* @return value of the block if can be counted
|
||||||
*/
|
*/
|
||||||
private int limitCount(Material md) {
|
private int limitCount(Material md) {
|
||||||
if (limitCount.containsKey(md)) {
|
if (limitCount.containsKey(md)) {
|
||||||
int count = limitCount.get(md);
|
int count = limitCount.get(md);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
limitCount.put(md, --count);
|
limitCount.put(md, --count);
|
||||||
return getValue(md);
|
return getValue(md);
|
||||||
} else {
|
} else {
|
||||||
results.ofCount.add(md);
|
results.ofCount.add(md);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getValue(md);
|
return getValue(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -355,39 +353,39 @@ public class IslandLevelCalculator {
|
|||||||
* @param chunk - the chunk to scan
|
* @param chunk - the chunk to scan
|
||||||
*/
|
*/
|
||||||
private void scanChests(Chunk chunk) {
|
private void scanChests(Chunk chunk) {
|
||||||
// Count blocks in chests
|
// Count blocks in chests
|
||||||
for (BlockState bs : chunk.getTileEntities()) {
|
for (BlockState bs : chunk.getTileEntities()) {
|
||||||
if (bs instanceof Container container) {
|
if (bs instanceof Container container) {
|
||||||
if (addon.isAdvChestEnabled()) {
|
if (addon.isAdvChestEnabled()) {
|
||||||
AdvancedChest<?, ?> aChest = AdvancedChestsAPI.getChestManager().getAdvancedChest(bs.getLocation());
|
AdvancedChest<?, ?> aChest = AdvancedChestsAPI.getChestManager().getAdvancedChest(bs.getLocation());
|
||||||
if (aChest != null && aChest.getChestType().getName().equals("NORMAL")) {
|
if (aChest != null && aChest.getChestType().getName().equals("NORMAL")) {
|
||||||
aChest.getPages().stream().map(ChestPage::getItems).forEach(c -> {
|
aChest.getPages().stream().map(ChestPage::getItems).forEach(c -> {
|
||||||
for (Object i : c) {
|
for (Object i : c) {
|
||||||
countItemStack((ItemStack) i);
|
countItemStack((ItemStack) i);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Regular chest
|
// Regular chest
|
||||||
container.getSnapshotInventory().forEach(this::countItemStack);
|
container.getSnapshotInventory().forEach(this::countItemStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void countItemStack(ItemStack i) {
|
private void countItemStack(ItemStack i) {
|
||||||
if (i == null || !i.getType().isBlock())
|
if (i == null || !i.getType().isBlock())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int c = 0; c < i.getAmount(); c++) {
|
for (int c = 0; c < i.getAmount(); c++) {
|
||||||
if (addon.getSettings().isIncludeShulkersInChest()
|
if (addon.getSettings().isIncludeShulkersInChest()
|
||||||
&& i.getItemMeta() instanceof BlockStateMeta blockStateMeta
|
&& i.getItemMeta() instanceof BlockStateMeta blockStateMeta
|
||||||
&& blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox) {
|
&& blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox) {
|
||||||
shulkerBox.getSnapshotInventory().forEach(this::countItemStack);
|
shulkerBox.getSnapshotInventory().forEach(this::countItemStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkBlock(i.getType(), false);
|
checkBlock(i.getType(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -400,26 +398,26 @@ public class IslandLevelCalculator {
|
|||||||
* that will be true if the scan was successful, false if not
|
* that will be true if the scan was successful, false if not
|
||||||
*/
|
*/
|
||||||
private CompletableFuture<Boolean> scanChunk(List<Chunk> chunks) {
|
private CompletableFuture<Boolean> scanChunk(List<Chunk> chunks) {
|
||||||
// If the chunk hasn't been generated, return
|
// If the chunk hasn't been generated, return
|
||||||
if (chunks == null || chunks.isEmpty()) {
|
if (chunks == null || chunks.isEmpty()) {
|
||||||
return CompletableFuture.completedFuture(false);
|
return CompletableFuture.completedFuture(false);
|
||||||
}
|
}
|
||||||
// Count blocks in chunk
|
// Count blocks in chunk
|
||||||
CompletableFuture<Boolean> result = new CompletableFuture<>();
|
CompletableFuture<Boolean> result = new CompletableFuture<>();
|
||||||
/*
|
/*
|
||||||
* At this point, we need to grab a snapshot of each chunk and then scan it
|
* At this point, we need to grab a snapshot of each chunk and then scan it
|
||||||
* async. At the end, we make the CompletableFuture true to show it is done. I'm
|
* async. At the end, we make the CompletableFuture true to show it is done. I'm
|
||||||
* not sure how much lag this will cause, but as all the chunks are loaded,
|
* not sure how much lag this will cause, but as all the chunks are loaded,
|
||||||
* maybe not that much.
|
* maybe not that much.
|
||||||
*/
|
*/
|
||||||
List<ChunkPair> preLoad = chunks.stream().map(c -> new ChunkPair(c.getWorld(), c, c.getChunkSnapshot()))
|
List<ChunkPair> preLoad = chunks.stream().map(c -> new ChunkPair(c.getWorld(), c, c.getChunkSnapshot()))
|
||||||
.toList();
|
.toList();
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () -> {
|
||||||
preLoad.forEach(this::scanAsync);
|
preLoad.forEach(this::scanAsync);
|
||||||
// Once they are all done, return to the main thread.
|
// Once they are all done, return to the main thread.
|
||||||
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> result.complete(true));
|
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> result.complete(true));
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
record ChunkPair(World world, Chunk chunk, ChunkSnapshot chunkSnapshot) {
|
record ChunkPair(World world, Chunk chunk, ChunkSnapshot chunkSnapshot) {
|
||||||
@ -431,66 +429,53 @@ public class IslandLevelCalculator {
|
|||||||
* @param cp chunk to scan
|
* @param cp chunk to scan
|
||||||
*/
|
*/
|
||||||
private void scanAsync(ChunkPair cp) {
|
private void scanAsync(ChunkPair cp) {
|
||||||
for (int x = 0; x < 16; x++) {
|
for (int x = 0; x < 16; x++) {
|
||||||
// Check if the block coordinate is inside the protection zone and if not, don't
|
// Check if the block coordinate is inside the protection zone and if not, don't
|
||||||
// count it
|
// count it
|
||||||
if (cp.chunkSnapshot.getX() * 16 + x < island.getMinProtectedX() || cp.chunkSnapshot.getX() * 16
|
if (cp.chunkSnapshot.getX() * 16 + x < island.getMinProtectedX() || cp.chunkSnapshot.getX() * 16
|
||||||
+ x >= island.getMinProtectedX() + island.getProtectionRange() * 2) {
|
+ x >= island.getMinProtectedX() + island.getProtectionRange() * 2) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int z = 0; z < 16; z++) {
|
for (int z = 0; z < 16; z++) {
|
||||||
// Check if the block coordinate is inside the protection zone and if not, don't
|
// Check if the block coordinate is inside the protection zone and if not, don't
|
||||||
// count it
|
// count it
|
||||||
if (cp.chunkSnapshot.getZ() * 16 + z < island.getMinProtectedZ() || cp.chunkSnapshot.getZ() * 16
|
if (cp.chunkSnapshot.getZ() * 16 + z < island.getMinProtectedZ() || cp.chunkSnapshot.getZ() * 16
|
||||||
+ z >= island.getMinProtectedZ() + island.getProtectionRange() * 2) {
|
+ z >= island.getMinProtectedZ() + island.getProtectionRange() * 2) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Only count to the highest block in the world for some optimization
|
// Only count to the highest block in the world for some optimization
|
||||||
for (int y = cp.world.getMinHeight(); y < cp.world.getMaxHeight(); y++) {
|
for (int y = cp.world.getMinHeight(); y < cp.world.getMaxHeight(); y++) {
|
||||||
BlockData blockData = cp.chunkSnapshot.getBlockData(x, y, z);
|
BlockData blockData = cp.chunkSnapshot.getBlockData(x, y, z);
|
||||||
boolean belowSeaLevel = seaHeight > 0 && y <= seaHeight;
|
Material m = blockData.getMaterial();
|
||||||
// Slabs can be doubled, so check them twice
|
boolean belowSeaLevel = seaHeight > 0 && y <= seaHeight;
|
||||||
if (Tag.SLABS.isTagged(blockData.getMaterial())) {
|
// Slabs can be doubled, so check them twice
|
||||||
Slab slab = (Slab) blockData;
|
if (Tag.SLABS.isTagged(m)) {
|
||||||
if (slab.getType().equals(Slab.Type.DOUBLE)) {
|
Slab slab = (Slab) blockData;
|
||||||
checkBlock(blockData.getMaterial(), belowSeaLevel);
|
if (slab.getType().equals(Slab.Type.DOUBLE)) {
|
||||||
}
|
checkBlock(m, belowSeaLevel);
|
||||||
}
|
}
|
||||||
// Hook for Wild Stackers (Blocks and Spawners Only) - this has to use the real
|
}
|
||||||
// chunk
|
// Hook for Wild Stackers (Blocks and Spawners Only) - this has to use the real
|
||||||
if (addon.isStackersEnabled() && (blockData.getMaterial().equals(Material.CAULDRON)
|
// chunk
|
||||||
|| blockData.getMaterial().equals(Material.SPAWNER))) {
|
if (addon.isStackersEnabled() && (m.equals(Material.CAULDRON) || m.equals(Material.SPAWNER))) {
|
||||||
stackedBlocks.add(new Location(cp.world, (double) x + cp.chunkSnapshot.getX() * 16, y,
|
stackedBlocks.add(new Location(cp.world, (double) x + cp.chunkSnapshot.getX() * 16, y,
|
||||||
(double) z + cp.chunkSnapshot.getZ() * 16));
|
(double) z + cp.chunkSnapshot.getZ() * 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
Block block = cp.chunk.getBlock(x, y, z);
|
if (addon.isUltimateStackerEnabled() && !m.isAir()) {
|
||||||
|
Location l = new Location(cp.chunk.getWorld(), x, y, z);
|
||||||
|
UltimateStackerCalc.addStackers(m, l, results, belowSeaLevel, limitCount(m));
|
||||||
|
}
|
||||||
|
|
||||||
if (addon.isUltimateStackerEnabled()) {
|
// Scan chests
|
||||||
if (!blockData.getMaterial().equals(Material.AIR)) {
|
if (addon.getSettings().isIncludeChests() && CHESTS.contains(m)) {
|
||||||
Stackable stack = UltimateStackerApi.getBlockStackManager().getBlock(block.getLocation());
|
chestBlocks.add(cp.chunk);
|
||||||
if (stack != null) {
|
}
|
||||||
int value = limitCount(blockData.getMaterial());
|
// Add the value of the block's material
|
||||||
if (belowSeaLevel) {
|
checkBlock(m, belowSeaLevel);
|
||||||
results.underWaterBlockCount.addAndGet((long) stack.getAmount() * value);
|
}
|
||||||
results.uwCount.add(blockData.getMaterial());
|
}
|
||||||
} else {
|
}
|
||||||
results.rawBlockCount.addAndGet((long) stack.getAmount() * value);
|
|
||||||
results.mdCount.add(blockData.getMaterial());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan chests
|
|
||||||
if (addon.getSettings().isIncludeChests() && CHESTS.contains(blockData.getMaterial())) {
|
|
||||||
chestBlocks.add(cp.chunk);
|
|
||||||
}
|
|
||||||
// Add the value of the block's material
|
|
||||||
checkBlock(blockData.getMaterial(), belowSeaLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -500,180 +485,180 @@ public class IslandLevelCalculator {
|
|||||||
* to be scanned, and false if not
|
* to be scanned, and false if not
|
||||||
*/
|
*/
|
||||||
public CompletableFuture<Boolean> scanNextChunk() {
|
public CompletableFuture<Boolean> scanNextChunk() {
|
||||||
if (chunksToCheck.isEmpty()) {
|
if (chunksToCheck.isEmpty()) {
|
||||||
addon.logError("Unexpected: no chunks to scan!");
|
addon.logError("Unexpected: no chunks to scan!");
|
||||||
// This should not be needed, but just in case
|
// This should not be needed, but just in case
|
||||||
return CompletableFuture.completedFuture(false);
|
return CompletableFuture.completedFuture(false);
|
||||||
}
|
}
|
||||||
// Retrieve and remove from the queue
|
// Retrieve and remove from the queue
|
||||||
Queue<Pair<Integer, Integer>> pairList = new ConcurrentLinkedQueue<>();
|
Queue<Pair<Integer, Integer>> pairList = new ConcurrentLinkedQueue<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (!chunksToCheck.isEmpty() && i++ < CHUNKS_TO_SCAN) {
|
while (!chunksToCheck.isEmpty() && i++ < CHUNKS_TO_SCAN) {
|
||||||
pairList.add(chunksToCheck.poll());
|
pairList.add(chunksToCheck.poll());
|
||||||
}
|
}
|
||||||
Queue<Pair<Integer, Integer>> endPairList = new ConcurrentLinkedQueue<>(pairList);
|
Queue<Pair<Integer, Integer>> endPairList = new ConcurrentLinkedQueue<>(pairList);
|
||||||
Queue<Pair<Integer, Integer>> netherPairList = new ConcurrentLinkedQueue<>(pairList);
|
Queue<Pair<Integer, Integer>> netherPairList = new ConcurrentLinkedQueue<>(pairList);
|
||||||
// Set up the result
|
// Set up the result
|
||||||
CompletableFuture<Boolean> result = new CompletableFuture<>();
|
CompletableFuture<Boolean> result = new CompletableFuture<>();
|
||||||
// Get chunks and scan
|
// Get chunks and scan
|
||||||
// Get chunks and scan
|
// Get chunks and scan
|
||||||
getWorldChunk(Environment.THE_END, endPairList).thenAccept(
|
getWorldChunk(Environment.THE_END, endPairList).thenAccept(
|
||||||
endChunks -> scanChunk(endChunks).thenAccept(b -> getWorldChunk(Environment.NETHER, netherPairList)
|
endChunks -> scanChunk(endChunks).thenAccept(b -> getWorldChunk(Environment.NETHER, netherPairList)
|
||||||
.thenAccept(netherChunks -> scanChunk(netherChunks)
|
.thenAccept(netherChunks -> scanChunk(netherChunks)
|
||||||
.thenAccept(b2 -> getWorldChunk(Environment.NORMAL, pairList)
|
.thenAccept(b2 -> getWorldChunk(Environment.NORMAL, pairList)
|
||||||
.thenAccept(normalChunks -> scanChunk(normalChunks).thenAccept(b3 ->
|
.thenAccept(normalChunks -> scanChunk(normalChunks).thenAccept(b3 ->
|
||||||
// Complete the result now that all chunks have been scanned
|
// Complete the result now that all chunks have been scanned
|
||||||
result.complete(!chunksToCheck.isEmpty())))))));
|
result.complete(!chunksToCheck.isEmpty())))))));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<String> sortedReport(int total, Multiset<Material> materialCount) {
|
private Collection<String> sortedReport(int total, Multiset<Material> materialCount) {
|
||||||
Collection<String> result = new ArrayList<>();
|
Collection<String> result = new ArrayList<>();
|
||||||
Iterable<Multiset.Entry<Material>> entriesSortedByCount = Multisets.copyHighestCountFirst(materialCount)
|
Iterable<Multiset.Entry<Material>> entriesSortedByCount = Multisets.copyHighestCountFirst(materialCount)
|
||||||
.entrySet();
|
.entrySet();
|
||||||
for (Entry<Material> en : entriesSortedByCount) {
|
for (Entry<Material> en : entriesSortedByCount) {
|
||||||
Material type = en.getElement();
|
Material type = en.getElement();
|
||||||
|
|
||||||
int value = getValue(type);
|
int value = getValue(type);
|
||||||
|
|
||||||
result.add(type.toString() + ":" + String.format("%,d", en.getCount()) + " blocks x " + value + " = "
|
result.add(type.toString() + ":" + String.format("%,d", en.getCount()) + " blocks x " + value + " = "
|
||||||
+ (value * en.getCount()));
|
+ (value * en.getCount()));
|
||||||
total += (value * en.getCount());
|
total += (value * en.getCount());
|
||||||
|
|
||||||
}
|
}
|
||||||
result.add("Subtotal = " + total);
|
result.add("Subtotal = " + total);
|
||||||
result.add(LINE_BREAK);
|
result.add(LINE_BREAK);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finalizes the calculations and makes the report
|
* Finalizes the calculations and makes the report
|
||||||
*/
|
*/
|
||||||
public void tidyUp() {
|
public void tidyUp() {
|
||||||
// Finalize calculations
|
// Finalize calculations
|
||||||
results.rawBlockCount
|
results.rawBlockCount
|
||||||
.addAndGet((long) (results.underWaterBlockCount.get() * addon.getSettings().getUnderWaterMultiplier()));
|
.addAndGet((long) (results.underWaterBlockCount.get() * addon.getSettings().getUnderWaterMultiplier()));
|
||||||
|
|
||||||
// Set the death penalty
|
// Set the death penalty
|
||||||
if (this.addon.getSettings().isSumTeamDeaths()) {
|
if (this.addon.getSettings().isSumTeamDeaths()) {
|
||||||
for (UUID uuid : this.island.getMemberSet()) {
|
for (UUID uuid : this.island.getMemberSet()) {
|
||||||
this.results.deathHandicap.addAndGet(this.addon.getPlayers().getDeaths(island.getWorld(), uuid));
|
this.results.deathHandicap.addAndGet(this.addon.getPlayers().getDeaths(island.getWorld(), uuid));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// At this point, it may be that the island has become unowned.
|
// At this point, it may be that the island has become unowned.
|
||||||
this.results.deathHandicap.set(this.island.getOwner() == null ? 0
|
this.results.deathHandicap.set(this.island.getOwner() == null ? 0
|
||||||
: this.addon.getPlayers().getDeaths(island.getWorld(), this.island.getOwner()));
|
: this.addon.getPlayers().getDeaths(island.getWorld(), this.island.getOwner()));
|
||||||
}
|
}
|
||||||
|
|
||||||
long blockAndDeathPoints = this.results.rawBlockCount.get();
|
long blockAndDeathPoints = this.results.rawBlockCount.get();
|
||||||
this.results.totalPoints.set(blockAndDeathPoints);
|
this.results.totalPoints.set(blockAndDeathPoints);
|
||||||
|
|
||||||
if (this.addon.getSettings().getDeathPenalty() > 0) {
|
if (this.addon.getSettings().getDeathPenalty() > 0) {
|
||||||
// Proper death penalty calculation.
|
// Proper death penalty calculation.
|
||||||
blockAndDeathPoints -= this.results.deathHandicap.get() * this.addon.getSettings().getDeathPenalty();
|
blockAndDeathPoints -= this.results.deathHandicap.get() * this.addon.getSettings().getDeathPenalty();
|
||||||
}
|
}
|
||||||
this.results.level.set(calculateLevel(blockAndDeathPoints));
|
this.results.level.set(calculateLevel(blockAndDeathPoints));
|
||||||
|
|
||||||
// Calculate how many points are required to get to the next level
|
// Calculate how many points are required to get to the next level
|
||||||
long nextLevel = this.results.level.get();
|
long nextLevel = this.results.level.get();
|
||||||
long blocks = blockAndDeathPoints;
|
long blocks = blockAndDeathPoints;
|
||||||
while (nextLevel < this.results.level.get() + 1 && blocks - blockAndDeathPoints < MAX_AMOUNT) {
|
while (nextLevel < this.results.level.get() + 1 && blocks - blockAndDeathPoints < MAX_AMOUNT) {
|
||||||
nextLevel = calculateLevel(++blocks);
|
nextLevel = calculateLevel(++blocks);
|
||||||
}
|
}
|
||||||
this.results.pointsToNextLevel.set(blocks - blockAndDeathPoints);
|
this.results.pointsToNextLevel.set(blocks - blockAndDeathPoints);
|
||||||
|
|
||||||
// Report
|
// Report
|
||||||
results.report = getReport();
|
results.report = getReport();
|
||||||
// Set the duration
|
// Set the duration
|
||||||
addon.getPipeliner().setTime(System.currentTimeMillis() - duration);
|
addon.getPipeliner().setTime(System.currentTimeMillis() - duration);
|
||||||
// All done.
|
// All done.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the zeroIsland
|
* @return the zeroIsland
|
||||||
*/
|
*/
|
||||||
boolean isNotZeroIsland() {
|
boolean isNotZeroIsland() {
|
||||||
return !zeroIsland;
|
return !zeroIsland;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scanIsland(Pipeliner pipeliner) {
|
public void scanIsland(Pipeliner pipeliner) {
|
||||||
// Scan the next chunk
|
// Scan the next chunk
|
||||||
scanNextChunk().thenAccept(result -> {
|
scanNextChunk().thenAccept(result -> {
|
||||||
if (!Bukkit.isPrimaryThread()) {
|
if (!Bukkit.isPrimaryThread()) {
|
||||||
addon.getPlugin().logError("scanChunk not on Primary Thread!");
|
addon.getPlugin().logError("scanChunk not on Primary Thread!");
|
||||||
}
|
}
|
||||||
// Timeout check
|
// Timeout check
|
||||||
if (System.currentTimeMillis()
|
if (System.currentTimeMillis()
|
||||||
- pipeliner.getInProcessQueue().get(this) > addon.getSettings().getCalculationTimeout() * 60000) {
|
- pipeliner.getInProcessQueue().get(this) > addon.getSettings().getCalculationTimeout() * 60000) {
|
||||||
// Done
|
// Done
|
||||||
pipeliner.getInProcessQueue().remove(this);
|
pipeliner.getInProcessQueue().remove(this);
|
||||||
getR().complete(new Results(Result.TIMEOUT));
|
getR().complete(new Results(Result.TIMEOUT));
|
||||||
addon.logError("Level calculation timed out after " + addon.getSettings().getCalculationTimeout()
|
addon.logError("Level calculation timed out after " + addon.getSettings().getCalculationTimeout()
|
||||||
+ "m for island: " + getIsland());
|
+ "m for island: " + getIsland());
|
||||||
if (!isNotZeroIsland()) {
|
if (!isNotZeroIsland()) {
|
||||||
addon.logError("Island level was being zeroed.");
|
addon.logError("Island level was being zeroed.");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Boolean.TRUE.equals(result) && !pipeliner.getTask().isCancelled()) {
|
if (Boolean.TRUE.equals(result) && !pipeliner.getTask().isCancelled()) {
|
||||||
// scanNextChunk returns true if there are more chunks to scan
|
// scanNextChunk returns true if there are more chunks to scan
|
||||||
scanIsland(pipeliner);
|
scanIsland(pipeliner);
|
||||||
} else {
|
} else {
|
||||||
// Done
|
// Done
|
||||||
pipeliner.getInProcessQueue().remove(this);
|
pipeliner.getInProcessQueue().remove(this);
|
||||||
// Chunk finished
|
// Chunk finished
|
||||||
// This was the last chunk
|
// This was the last chunk
|
||||||
handleStackedBlocks();
|
handleStackedBlocks();
|
||||||
handleChests();
|
handleChests();
|
||||||
long checkTime = System.currentTimeMillis();
|
long checkTime = System.currentTimeMillis();
|
||||||
finishTask = Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> {
|
finishTask = Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> {
|
||||||
// Check every half second if all the chests and stacks have been cleared
|
// Check every half second if all the chests and stacks have been cleared
|
||||||
if ((chestBlocks.isEmpty() && stackedBlocks.isEmpty())
|
if ((chestBlocks.isEmpty() && stackedBlocks.isEmpty())
|
||||||
|| System.currentTimeMillis() - checkTime > MAX_AMOUNT) {
|
|| System.currentTimeMillis() - checkTime > MAX_AMOUNT) {
|
||||||
this.tidyUp();
|
this.tidyUp();
|
||||||
this.getR().complete(getResults());
|
this.getR().complete(getResults());
|
||||||
finishTask.cancel();
|
finishTask.cancel();
|
||||||
}
|
}
|
||||||
}, 0, 10L);
|
}, 0, 10L);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleChests() {
|
private void handleChests() {
|
||||||
Iterator<Chunk> it = chestBlocks.iterator();
|
Iterator<Chunk> it = chestBlocks.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Chunk v = it.next();
|
Chunk v = it.next();
|
||||||
Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> {
|
Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> {
|
||||||
scanChests(c);
|
scanChests(c);
|
||||||
it.remove();
|
it.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleStackedBlocks() {
|
private void handleStackedBlocks() {
|
||||||
// Deal with any stacked blocks
|
// Deal with any stacked blocks
|
||||||
Iterator<Location> it = stackedBlocks.iterator();
|
Iterator<Location> it = stackedBlocks.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Location v = it.next();
|
Location v = it.next();
|
||||||
Util.getChunkAtAsync(v).thenAccept(c -> {
|
Util.getChunkAtAsync(v).thenAccept(c -> {
|
||||||
Block stackedBlock = v.getBlock();
|
Block stackedBlock = v.getBlock();
|
||||||
boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight;
|
boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight;
|
||||||
if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) {
|
if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) {
|
||||||
StackedBarrel barrel = WildStackerAPI.getStackedBarrel(stackedBlock);
|
StackedBarrel barrel = WildStackerAPI.getStackedBarrel(stackedBlock);
|
||||||
int barrelAmt = WildStackerAPI.getBarrelAmount(stackedBlock);
|
int barrelAmt = WildStackerAPI.getBarrelAmount(stackedBlock);
|
||||||
for (int _x = 0; _x < barrelAmt; _x++) {
|
for (int _x = 0; _x < barrelAmt; _x++) {
|
||||||
checkBlock(barrel.getType(), belowSeaLevel);
|
checkBlock(barrel.getType(), belowSeaLevel);
|
||||||
}
|
}
|
||||||
} else if (WildStackerAPI.getWildStacker().getSystemManager().isStackedSpawner(stackedBlock)) {
|
} else if (WildStackerAPI.getWildStacker().getSystemManager().isStackedSpawner(stackedBlock)) {
|
||||||
int spawnerAmt = WildStackerAPI.getSpawnersAmount((CreatureSpawner) stackedBlock.getState());
|
int spawnerAmt = WildStackerAPI.getSpawnersAmount((CreatureSpawner) stackedBlock.getState());
|
||||||
for (int _x = 0; _x < spawnerAmt; _x++) {
|
for (int _x = 0; _x < spawnerAmt; _x++) {
|
||||||
checkBlock(stackedBlock.getType(), belowSeaLevel);
|
checkBlock(stackedBlock.getType(), belowSeaLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it.remove();
|
it.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package world.bentobox.level.calculators;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
import com.craftaro.ultimatestacker.api.UltimateStackerApi;
|
||||||
|
import com.craftaro.ultimatestacker.api.utils.Stackable;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Isolates UltimateStacker imports so that they are only loaded if the plugin exists
|
||||||
|
*/
|
||||||
|
public class UltimateStackerCalc {
|
||||||
|
public static void addStackers(Material material, Location location, Results results, boolean belowSeaLevel,
|
||||||
|
int value) {
|
||||||
|
Stackable stack = UltimateStackerApi.getBlockStackManager().getBlock(location);
|
||||||
|
if (stack != null) {
|
||||||
|
if (belowSeaLevel) {
|
||||||
|
results.underWaterBlockCount.addAndGet((long) stack.getAmount() * value);
|
||||||
|
results.uwCount.add(material);
|
||||||
|
} else {
|
||||||
|
results.rawBlockCount.addAndGet((long) stack.getAmount() * value);
|
||||||
|
results.mdCount.add(material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user