mirror of
https://github.com/songoda/FabledSkyBlock.git
synced 2025-02-17 04:02:04 +01:00
Optimized island scan
This commit is contained in:
parent
77cfd8a656
commit
ccbe8de7e0
@ -2,10 +2,14 @@ package com.songoda.skyblock.blockscanner;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.skyblock.SkyBlock;
|
||||
import com.songoda.skyblock.utils.version.NMSUtil;
|
||||
import com.songoda.skyblock.island.Island;
|
||||
import com.songoda.skyblock.island.IslandEnvironment;
|
||||
import com.songoda.skyblock.world.WorldManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
@ -19,6 +23,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public final class BlockScanner extends BukkitRunnable {
|
||||
|
||||
@ -29,9 +34,7 @@ public final class BlockScanner extends BukkitRunnable {
|
||||
|
||||
try {
|
||||
temp = ChunkSnapshot.class.getMethod("getBlockTypeId", int.class, int.class, int.class);
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
|
||||
}
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
|
||||
ID_FIELD = temp;
|
||||
}
|
||||
@ -49,22 +52,30 @@ public final class BlockScanner extends BukkitRunnable {
|
||||
return id;
|
||||
}
|
||||
|
||||
private final static int VERSION = NMSUtil.getVersionNumber();
|
||||
|
||||
private int completedNum;
|
||||
private final AtomicInteger completedNum;
|
||||
|
||||
private final int threadCount;
|
||||
private final Queue<BlockInfo> blocks;
|
||||
private final ScannerTasks tasks;
|
||||
|
||||
private final Island island;
|
||||
|
||||
private final boolean ignoreLiquids;
|
||||
private final boolean ignoreAir;
|
||||
|
||||
private BlockScanner(Map<World, List<ChunkSnapshot>> snapshots, boolean ignoreLiquids, boolean ignoreLiquidsY, boolean ignoreAir, boolean ignoreY, ScannerTasks tasks) {
|
||||
private BlockScanner(Map<World, List<ChunkSnapshot>> snapshots,
|
||||
Island island,
|
||||
boolean ignoreLiquids,
|
||||
boolean ignoreLiquidsY,
|
||||
boolean ignoreAir,
|
||||
boolean ignoreY,
|
||||
ScannerTasks tasks) {
|
||||
this.ignoreLiquids = ignoreLiquids;
|
||||
this.ignoreAir = ignoreAir;
|
||||
this.blocks = new ConcurrentLinkedQueue<>();
|
||||
this.tasks = tasks;
|
||||
this.completedNum = new AtomicInteger();
|
||||
this.island = island;
|
||||
|
||||
FileConfiguration config = SkyBlock.getInstance().getFileManager().getConfig(new File(SkyBlock.getInstance().getDataFolder(), "config.yml")).getFileConfiguration();
|
||||
|
||||
@ -73,7 +84,7 @@ public final class BlockScanner extends BukkitRunnable {
|
||||
for (Entry<World, List<ChunkSnapshot>> entry : snapshots.entrySet()) {
|
||||
|
||||
final List<List<ChunkSnapshot>> parts = Lists.partition(entry.getValue(), 16);
|
||||
|
||||
|
||||
threadCount += parts.size();
|
||||
|
||||
World world = entry.getKey();
|
||||
@ -109,21 +120,62 @@ public final class BlockScanner extends BukkitRunnable {
|
||||
}
|
||||
|
||||
private void queueWork(World world, int scanY, List<ChunkSnapshot> subList) {
|
||||
WorldManager worldManager = SkyBlock.getInstance().getWorldManager();
|
||||
|
||||
Bukkit.getServer().getScheduler().runTaskAsynchronously(SkyBlock.getInstance(), () -> {
|
||||
LocationBounds bounds = null;
|
||||
if(island != null) {
|
||||
Location islandLocation = island.getLocation(worldManager.getIslandWorld(world), IslandEnvironment.Island);
|
||||
|
||||
Location minLocation = new Location(world, islandLocation.getBlockX() - island.getRadius(), 0, islandLocation.getBlockZ() - island.getRadius());
|
||||
Location maxLocation = new Location(world, islandLocation.getBlockX() + island.getRadius(), world.getMaxHeight(), islandLocation.getBlockZ() + island.getRadius());
|
||||
|
||||
int minX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
int minZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
|
||||
int maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
int maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
|
||||
bounds = new LocationBounds(minX, minZ, maxX, maxZ);
|
||||
}
|
||||
for (ChunkSnapshot shot : subList) {
|
||||
|
||||
final int cX = shot.getX() << 4;
|
||||
final int cZ = shot.getZ() << 4;
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = scanY; y < shot.getHighestBlockYAt(x, z); y++) {
|
||||
|
||||
|
||||
final CompatibleMaterial type = CompatibleMaterial.getBlockMaterial(VERSION > 12
|
||||
? shot.getBlockType(x, y, z) : MaterialIDHelper.getLegacyMaterial(getBlockTypeID(shot, x, y, z)));
|
||||
|
||||
|
||||
|
||||
int initX = 0;
|
||||
int initZ = 0;
|
||||
int lastX = 15;
|
||||
int lastZ = 15;
|
||||
|
||||
if(bounds != null) {
|
||||
initX = Math.max(cX, bounds.getMinX())&0x000F;
|
||||
initZ = Math.max(cZ, bounds.getMinZ())&0x000F;
|
||||
|
||||
lastX = Math.min(cX | 15, bounds.getMaxX()-1)&0x000F;
|
||||
lastZ = Math.min(cZ | 15, bounds.getMaxZ()-1)&0x000F;
|
||||
}
|
||||
|
||||
int finalInitX = initX;
|
||||
int finalInitZ = initZ;
|
||||
int finalLastZ = lastZ;
|
||||
int finalLastX = lastX;
|
||||
Bukkit.getScheduler().runTask(SkyBlock.getInstance(), () -> {
|
||||
world.getChunkAt(shot.getX(), shot.getZ()).getBlock(finalInitX, 80, finalInitZ).setType(CompatibleMaterial.GOLD_BLOCK.getBlockMaterial());
|
||||
world.getChunkAt(shot.getX(), shot.getZ()).getBlock(finalLastX, 80, finalLastZ).setType(CompatibleMaterial.CRYING_OBSIDIAN.getBlockMaterial());
|
||||
Bukkit.getScheduler().runTaskLater(SkyBlock.getInstance(), () -> {
|
||||
world.getChunkAt(shot.getX(), shot.getZ()).getBlock(finalInitX, 80, finalInitZ).setType(CompatibleMaterial.AIR.getBlockMaterial());
|
||||
world.getChunkAt(shot.getX(), shot.getZ()).getBlock(finalLastX, 80, finalLastZ).setType(CompatibleMaterial.AIR.getBlockMaterial());
|
||||
}, 300L);
|
||||
});
|
||||
|
||||
for (int x = initX; x <= lastX; x++) {
|
||||
for (int z = initZ; z <= lastZ; z++) {
|
||||
for (int y = scanY; y < world.getMaxHeight(); y++) {
|
||||
final CompatibleMaterial type = CompatibleMaterial.getBlockMaterial(
|
||||
ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
|
||||
? shot.getBlockType(x, y, z) :
|
||||
MaterialIDHelper.getLegacyMaterial(getBlockTypeID(shot, x, y, z)));
|
||||
|
||||
if(type == null){
|
||||
continue;
|
||||
} else if(type.equals(CompatibleMaterial.AIR) && ignoreAir){
|
||||
@ -142,12 +194,11 @@ public final class BlockScanner extends BukkitRunnable {
|
||||
}
|
||||
|
||||
private synchronized int increment() {
|
||||
completedNum += 1;
|
||||
return completedNum;
|
||||
return completedNum.getAndIncrement();
|
||||
}
|
||||
|
||||
private synchronized int get() {
|
||||
return completedNum;
|
||||
return completedNum.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,12 +209,12 @@ public final class BlockScanner extends BukkitRunnable {
|
||||
cancel();
|
||||
}
|
||||
|
||||
public static void startScanner(Map<World, List<ChunkSnapshot>> snapshots, boolean ignoreLiquids, boolean ignoreLiquidsY, boolean ignoreAir, boolean ignoreY, ScannerTasks tasks) {
|
||||
public static void startScanner(Map<World, List<ChunkSnapshot>> snapshots, Island island, boolean ignoreLiquids, boolean ignoreLiquidsY, boolean ignoreAir, boolean ignoreY, ScannerTasks tasks) {
|
||||
|
||||
if (snapshots == null) throw new IllegalArgumentException("snapshots cannot be null");
|
||||
if (tasks == null) throw new IllegalArgumentException("tasks cannot be null");
|
||||
|
||||
final BlockScanner scanner = new BlockScanner(snapshots, ignoreLiquids, ignoreLiquidsY, ignoreAir, ignoreY, tasks);
|
||||
final BlockScanner scanner = new BlockScanner(snapshots, island, ignoreLiquids, ignoreLiquidsY, ignoreAir, ignoreY, tasks);
|
||||
|
||||
scanner.runTaskTimer(SkyBlock.getInstance(), 5, 5);
|
||||
}
|
||||
|
@ -20,19 +20,24 @@ public class ChunkLoader extends BukkitRunnable {
|
||||
|
||||
private ChunkScannerTask generalTask;
|
||||
private ChunkForChunkScannerTask chunkTask;
|
||||
private boolean chunkForChunk;
|
||||
private boolean paper;
|
||||
private final boolean chunkForChunk;
|
||||
private final boolean paper;
|
||||
private World world;
|
||||
private Island island;
|
||||
private final Island island;
|
||||
private int x;
|
||||
private int z;
|
||||
private int minZ;
|
||||
private int maxX;
|
||||
private int maxZ;
|
||||
private int chunkPerTick;
|
||||
private CompleteTask completeTask;
|
||||
private final int chunkPerTick;
|
||||
private final CompleteTask completeTask;
|
||||
|
||||
private ChunkLoader(Island island, IslandWorld islandWorld, boolean paper, boolean chunkForChunk, ChunkForChunkScannerTask chunkTask, CompleteTask complete) {
|
||||
private ChunkLoader(Island island,
|
||||
IslandWorld islandWorld,
|
||||
boolean paper,
|
||||
boolean chunkForChunk,
|
||||
ChunkForChunkScannerTask chunkTask,
|
||||
CompleteTask complete) {
|
||||
chunkPerTick = SkyBlock.getInstance().getFileManager()
|
||||
.getConfig(new File(SkyBlock.getInstance().getDataFolder(), "config.yml"))
|
||||
.getFileConfiguration().getInt("Island.Performance.ChunkPerTick", 25);
|
||||
@ -51,11 +56,11 @@ public class ChunkLoader extends BukkitRunnable {
|
||||
Location minLocation = new Location(world, islandLocation.getBlockX() - island.getRadius(), 0, islandLocation.getBlockZ() - island.getRadius());
|
||||
Location maxLocation = new Location(world, islandLocation.getBlockX() + island.getRadius(), world.getMaxHeight(), islandLocation.getBlockZ() + island.getRadius());
|
||||
|
||||
int minX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
minZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
int minX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX()) >> 4 << 4 ;
|
||||
minZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ()) >> 4 << 4;
|
||||
|
||||
maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX()) >> 4 << 4 | 15;
|
||||
maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ()) >> 4 << 4 | 15;
|
||||
|
||||
x = minX;
|
||||
z = minZ;
|
||||
@ -67,7 +72,12 @@ public class ChunkLoader extends BukkitRunnable {
|
||||
}
|
||||
}
|
||||
|
||||
private ChunkLoader(Island island, IslandWorld islandWorld, boolean paper, boolean chunkForChunk, ChunkScannerTask generalTask, CompleteTask complete) {
|
||||
private ChunkLoader(Island island,
|
||||
IslandWorld islandWorld,
|
||||
boolean paper,
|
||||
boolean chunkForChunk,
|
||||
ChunkScannerTask generalTask,
|
||||
CompleteTask complete) {
|
||||
chunkPerTick = SkyBlock.getInstance().getFileManager()
|
||||
.getConfig(new File(SkyBlock.getInstance().getDataFolder(), "config.yml"))
|
||||
.getFileConfiguration().getInt("Island.Performance.ChunkPerTick", 25);
|
||||
@ -83,18 +93,26 @@ public class ChunkLoader extends BukkitRunnable {
|
||||
|
||||
world = islandLocation.getWorld();
|
||||
|
||||
Location minLocation = new Location(world, islandLocation.getBlockX() - island.getRadius(), 0, islandLocation.getBlockZ() - island.getRadius());
|
||||
Location maxLocation = new Location(world, islandLocation.getBlockX() + island.getRadius(), world.getMaxHeight(), islandLocation.getBlockZ() + island.getRadius());
|
||||
Location minLocation = new Location(
|
||||
world,
|
||||
islandLocation.getBlockX() - island.getRadius(),
|
||||
0,
|
||||
islandLocation.getBlockZ() - island.getRadius());
|
||||
Location maxLocation = new Location(
|
||||
world,
|
||||
islandLocation.getBlockX() + island.getRadius(),
|
||||
world.getMaxHeight(),
|
||||
islandLocation.getBlockZ() + island.getRadius());
|
||||
|
||||
int minX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX()) >> 4 << 4;
|
||||
minZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ()) >> 4 << 4;
|
||||
|
||||
int minX = Math.min(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
minZ = Math.min(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
|
||||
maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX()) >> 4 << 4 | 15;
|
||||
maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ()) >> 4 << 4 | 15;
|
||||
|
||||
x = minX;
|
||||
z = minZ;
|
||||
|
||||
|
||||
if(paper){
|
||||
this.runTaskAsynchronously(SkyBlock.getInstance());
|
||||
} else {
|
||||
@ -105,8 +123,8 @@ public class ChunkLoader extends BukkitRunnable {
|
||||
@Override
|
||||
public void run() { // TODO New algorithm that start from the center of the island
|
||||
for(int i = 0; i < chunkPerTick || paper; i++){
|
||||
if(x < maxX){
|
||||
if(z < maxZ){
|
||||
if(x <= maxX){
|
||||
if(z <= maxZ){
|
||||
if(!chunkForChunk){
|
||||
positions.add(PaperLib.getChunkAtAsync(world, x >> 4, z >> 4));
|
||||
} else {
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.songoda.skyblock.blockscanner;
|
||||
|
||||
public class LocationBounds {
|
||||
private final int minX, minZ, maxX, maxZ;
|
||||
|
||||
public LocationBounds(int minX, int minZ, int maxX, int maxZ) {
|
||||
this.minX = minX;
|
||||
this.minZ = minZ;
|
||||
this.maxX = maxX;
|
||||
this.maxZ = maxZ;
|
||||
}
|
||||
|
||||
public int getMinX() {
|
||||
return minX;
|
||||
}
|
||||
|
||||
public int getMinZ() {
|
||||
return minZ;
|
||||
}
|
||||
|
||||
public int getMaxX() {
|
||||
return maxX;
|
||||
}
|
||||
|
||||
public int getMaxZ() {
|
||||
return maxZ;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.songoda.skyblock.blockscanner;
|
||||
|
||||
import com.songoda.skyblock.utils.version.NMSUtil;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -9,18 +9,14 @@ import java.util.Map;
|
||||
@SuppressWarnings("deprecation")
|
||||
public final class MaterialIDHelper {
|
||||
|
||||
private final static int VERSION = NMSUtil.getVersionNumber();
|
||||
|
||||
private MaterialIDHelper() {
|
||||
|
||||
}
|
||||
private MaterialIDHelper() {}
|
||||
|
||||
private final static Map<Integer, Material> MATERIALS;
|
||||
|
||||
static {
|
||||
MATERIALS = new HashMap<>();
|
||||
|
||||
if (VERSION > 12) {
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
|
||||
for (Material type : Material.values()) {
|
||||
if (type.isLegacy()) MATERIALS.put(type.getId(), type);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public class ChunkDeleteSplitter extends BukkitRunnable {
|
||||
}
|
||||
|
||||
private void start() {
|
||||
BlockScanner.startScanner(snapshots, false, true, true, false, (blocks) -> {
|
||||
BlockScanner.startScanner(snapshots, null,false, true, true, false, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
});
|
||||
|
@ -12,7 +12,10 @@ import com.songoda.skyblock.island.IslandWorld;
|
||||
import com.songoda.skyblock.levelling.amount.AmountMaterialPair;
|
||||
import com.songoda.skyblock.levelling.amount.BlockAmount;
|
||||
import com.songoda.skyblock.message.MessageManager;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -22,8 +25,6 @@ import java.io.File;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class IslandScan extends BukkitRunnable {
|
||||
|
||||
@ -81,28 +82,25 @@ public final class IslandScan extends BukkitRunnable {
|
||||
populate(snapshots, IslandWorld.Nether, plugin.isPaperAsync(), () -> {
|
||||
if (hasEnd) {
|
||||
populate(snapshots, IslandWorld.End, plugin.isPaperAsync(), () -> {
|
||||
BlockScanner.startScanner(snapshots, true, true, true, false, (blocks) -> {
|
||||
BlockScanner.startScanner(snapshots, island, true, true, true, false, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.blocksSize = blocks.size();
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
|
||||
});
|
||||
});
|
||||
} else {
|
||||
BlockScanner.startScanner(snapshots, true, true, true, false, (blocks) -> {
|
||||
BlockScanner.startScanner(snapshots, island, true, true, true, false, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.blocksSize = blocks.size();
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
BlockScanner.startScanner(snapshots, true, true, true, false, (blocks) -> {
|
||||
BlockScanner.startScanner(snapshots, island, true, true, true, false, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.blocksSize = blocks.size();
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -169,8 +167,12 @@ public final class IslandScan extends BukkitRunnable {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
if (language.getBoolean("Command.Island.Level.Scanning.Progress.Should-Display-Message") && executions == 1 || totalScanned == blocksSize || executions % runEveryX == 0) {
|
||||
|
||||
final double percent = ((double) totalScanned / (double) blocksSize) * 100;
|
||||
double percent = ((double) totalScanned / (double) blocksSize) * 100;
|
||||
|
||||
if(Double.isNaN(percent)) {
|
||||
percent = 0d;
|
||||
}
|
||||
|
||||
String message = language.getString("Command.Island.Level.Scanning.Progress.Message");
|
||||
message = message.replace("%current_scanned_blocks%", String.valueOf(totalScanned));
|
||||
message = message.replace("%max_blocks%", String.valueOf(blocksSize));
|
||||
|
Loading…
Reference in New Issue
Block a user