mirror of
https://github.com/songoda/FabledSkyBlock.git
synced 2024-06-28 23:54:57 +02:00
Fix for issues scanning or deleting an island in Paper with async chunk loads
This commit is contained in:
parent
4ab5fa01ed
commit
30e4637d3f
6
pom.xml
6
pom.xml
|
@ -127,9 +127,9 @@
|
|||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.15</version>
|
||||
<groupId>com.destroystokyo.papermc</groupId>
|
||||
<artifactId>paper</artifactId>
|
||||
<version>1.15.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -93,6 +93,8 @@ public class SkyBlock extends SongodaPlugin {
|
|||
|
||||
private CoreProtectAPI coreProtectAPI;
|
||||
|
||||
private boolean paper;
|
||||
|
||||
private final GuiManager guiManager = new GuiManager(this);
|
||||
|
||||
public static SkyBlock getInstance() {
|
||||
|
@ -106,6 +108,14 @@ public class SkyBlock extends SongodaPlugin {
|
|||
|
||||
@Override
|
||||
public void onPluginEnable() {
|
||||
|
||||
paper = false;
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.PaperConfig");
|
||||
paper = true;
|
||||
Bukkit.getLogger().info("Enabling Paper hooks");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
// Run Songoda Updater
|
||||
SongodaCore.registerPlugin(this, 17, CompatibleMaterial.GRASS_BLOCK);
|
||||
|
||||
|
@ -135,7 +145,7 @@ public class SkyBlock extends SongodaPlugin {
|
|||
|
||||
inviteManager = new InviteManager(this);
|
||||
biomeManager = new BiomeManager(this);
|
||||
levellingManager = new IslandLevelManager();
|
||||
levellingManager = new IslandLevelManager(this);
|
||||
commandManager = new CommandManager(this);
|
||||
structureManager = new StructureManager(this);
|
||||
soundManager = new SoundManager(this);
|
||||
|
@ -415,4 +425,8 @@ public class SkyBlock extends SongodaPlugin {
|
|||
public CoreProtectAPI getCoreProtectAPI() {
|
||||
return coreProtectAPI;
|
||||
}
|
||||
|
||||
public boolean isPaper() {
|
||||
return paper;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.songoda.skyblock.cooldown.CooldownType;
|
|||
import com.songoda.skyblock.invite.Invite;
|
||||
import com.songoda.skyblock.invite.InviteManager;
|
||||
import com.songoda.skyblock.island.removal.ChunkDeleteSplitter;
|
||||
import com.songoda.skyblock.levelling.ChunkUtil;
|
||||
import com.songoda.skyblock.message.MessageManager;
|
||||
import com.songoda.skyblock.playerdata.PlayerData;
|
||||
import com.songoda.skyblock.playerdata.PlayerDataManager;
|
||||
|
@ -56,6 +57,7 @@ import org.bukkit.plugin.Plugin;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class IslandManager {
|
||||
|
@ -556,22 +558,15 @@ public class IslandManager {
|
|||
}
|
||||
}
|
||||
|
||||
final Map<World, List<ChunkSnapshot>> snapshots = new HashMap<>(3);
|
||||
|
||||
for (IslandWorld worldList : IslandWorld.getIslandWorlds()) {
|
||||
|
||||
final Location location = island.getLocation(worldList, IslandEnvironment.Island);
|
||||
|
||||
if (location == null) continue;
|
||||
|
||||
final World world = worldManager.getWorld(worldList);
|
||||
|
||||
final List<ChunkSnapshot> list = com.songoda.skyblock.levelling.ChunkUtil.getChunksToScan(island, worldList).stream().map(chunk -> chunk.getChunkSnapshot()).collect(Collectors.toList());
|
||||
|
||||
snapshots.put(world, list);
|
||||
if (skyblock.isPaper() && Bukkit.spigot().getPaperConfig().getBoolean("settings.async-chunks.enable", false)) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(skyblock, () -> {
|
||||
startDeletition(island, worldManager);
|
||||
});
|
||||
} else {
|
||||
startDeletition(island, worldManager);
|
||||
}
|
||||
|
||||
ChunkDeleteSplitter.startDeletion(snapshots);
|
||||
|
||||
|
||||
skyblock.getVisitManager().deleteIsland(island.getOwnerUUID());
|
||||
skyblock.getBanManager().deleteIsland(island.getOwnerUUID());
|
||||
|
@ -657,6 +652,40 @@ public class IslandManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void startDeletition(Island island, WorldManager worldManager) {
|
||||
final Map<World, List<ChunkSnapshot>> snapshots = new HashMap<>(3);
|
||||
|
||||
for (IslandWorld worldList : IslandWorld.getIslandWorlds()) {
|
||||
|
||||
final Location location = island.getLocation(worldList, IslandEnvironment.Island);
|
||||
|
||||
if (location == null) continue;
|
||||
|
||||
final World world = worldManager.getWorld(worldList);
|
||||
|
||||
ChunkUtil chunks = new ChunkUtil();
|
||||
|
||||
|
||||
if (skyblock.isPaper() && Bukkit.spigot().getPaperConfig().getBoolean("settings.async-chunks.enable", false)) {
|
||||
chunks.getChunksToScan(island, worldList, true);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(skyblock, () -> {
|
||||
List<Chunk> positions = new LinkedList<>();
|
||||
for (CompletableFuture<Chunk> chunk : chunks.asyncPositions) {
|
||||
positions.add(chunk.join());
|
||||
snapshots.put(world, positions.stream().map(Chunk::getChunkSnapshot).collect(Collectors.toList()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
chunks.getChunksToScan(island, worldList, false);
|
||||
final List<ChunkSnapshot> list = chunks.syncPositions.stream().map(Chunk::getChunkSnapshot).collect(Collectors.toList());
|
||||
|
||||
snapshots.put(world, list);
|
||||
}
|
||||
}
|
||||
|
||||
ChunkDeleteSplitter.startDeletion(snapshots);
|
||||
}
|
||||
|
||||
public synchronized void deleteIslandData(UUID uuid) {
|
||||
FileManager fileManager = skyblock.getFileManager();
|
||||
fileManager.deleteConfig(new File(skyblock.getDataFolder().toString() + "/island-data", uuid.toString() + ".yml"));
|
||||
|
|
|
@ -3,7 +3,9 @@ package com.songoda.skyblock.levelling;
|
|||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.paperlib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
@ -13,11 +15,13 @@ import com.songoda.skyblock.island.IslandEnvironment;
|
|||
import com.songoda.skyblock.island.IslandWorld;
|
||||
|
||||
public class ChunkUtil {
|
||||
public final List<CompletableFuture<Chunk>> asyncPositions = new LinkedList<>();
|
||||
public final List<Chunk> syncPositions = new LinkedList<>();
|
||||
|
||||
public static List<Chunk> getChunksToScan(Island island, IslandWorld islandWorld) {
|
||||
public void getChunksToScan(Island island, IslandWorld islandWorld, boolean paper) {
|
||||
Location islandLocation = island.getLocation(islandWorld, IslandEnvironment.Island);
|
||||
|
||||
if (islandLocation == null) return new ArrayList<>(0);
|
||||
if (islandLocation == null) return;
|
||||
|
||||
World world = islandLocation.getWorld();
|
||||
|
||||
|
@ -30,14 +34,15 @@ public class ChunkUtil {
|
|||
int maxX = Math.max(maxLocation.getBlockX(), minLocation.getBlockX());
|
||||
int maxZ = Math.max(maxLocation.getBlockZ(), minLocation.getBlockZ());
|
||||
|
||||
final List<Chunk> positions = new LinkedList<>();
|
||||
|
||||
for (int x = minX; x < maxX + 16; x += 16) {
|
||||
for (int z = minZ; z < maxZ + 16; z += 16) {
|
||||
positions.add(world.getChunkAt(x >> 4, z >> 4));
|
||||
if(paper){
|
||||
asyncPositions.add(PaperLib.getChunkAtAsync(world, x >> 4, z >> 4));
|
||||
} else {
|
||||
syncPositions.add(world.getChunkAt(x >> 4, z >> 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,10 @@ public final class IslandLevelManager {
|
|||
private Map<Island, IslandScan> inScan;
|
||||
private Map<CompatibleMaterial, Long> worth;
|
||||
private Map<CompatibleMaterial, AmountMaterialPair> cachedPairs;
|
||||
private final SkyBlock plugin;
|
||||
|
||||
public IslandLevelManager() {
|
||||
public IslandLevelManager(SkyBlock plugin) {
|
||||
this.plugin = plugin;
|
||||
this.inScan = new HashMap<>();
|
||||
this.worth = new EnumMap<>(CompatibleMaterial.class);
|
||||
this.cachedPairs = new EnumMap<>(CompatibleMaterial.class);
|
||||
|
@ -46,8 +48,7 @@ public final class IslandLevelManager {
|
|||
reloadWorth();
|
||||
}
|
||||
|
||||
public void startScan(Player attemptScanner, Island island) {
|
||||
|
||||
public void startScan(Player attemptScanner, Island island){
|
||||
if (!Bukkit.isPrimaryThread()) {
|
||||
Bukkit.getScheduler().runTask(SkyBlock.getInstance(), () -> startScan(attemptScanner, island));
|
||||
return;
|
||||
|
@ -73,7 +74,7 @@ public final class IslandLevelManager {
|
|||
messageManager.sendMessage(attemptScanner, config.getString("Command.Island.Level.Scanning.Started.Message"));
|
||||
}
|
||||
|
||||
inScan.put(island, new IslandScan(island).start());
|
||||
inScan.put(island, new IslandScan(plugin, island).start());
|
||||
}
|
||||
|
||||
public boolean isScanning(Island island) {
|
||||
|
|
|
@ -12,10 +12,7 @@ import com.songoda.skyblock.levelling.ChunkUtil;
|
|||
import com.songoda.skyblock.levelling.rework.amount.AmountMaterialPair;
|
||||
import com.songoda.skyblock.levelling.rework.amount.BlockAmount;
|
||||
import com.songoda.skyblock.message.MessageManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -25,6 +22,7 @@ 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 {
|
||||
|
@ -37,13 +35,15 @@ public final class IslandScan extends BukkitRunnable {
|
|||
private final Map<CompatibleMaterial, BlockAmount> amounts;
|
||||
private final Configuration language;
|
||||
private final int runEveryX;
|
||||
private final SkyBlock plugin;
|
||||
|
||||
private int totalScanned;
|
||||
private int blocksSize;
|
||||
private Queue<BlockInfo> blocks;
|
||||
|
||||
public IslandScan(Island island) {
|
||||
public IslandScan(SkyBlock plugin, Island island) {
|
||||
if (island == null) throw new IllegalArgumentException("island cannot be null");
|
||||
this.plugin = plugin;
|
||||
this.island = island;
|
||||
this.amounts = new EnumMap<>(CompatibleMaterial.class);
|
||||
this.language = SkyBlock.getInstance().getFileManager().getConfig(new File(SkyBlock.getInstance().getDataFolder(), "language.yml")).getFileConfiguration();
|
||||
|
@ -62,16 +62,34 @@ public final class IslandScan extends BukkitRunnable {
|
|||
|
||||
final Map<World, List<ChunkSnapshot>> snapshots = new HashMap<>(3);
|
||||
|
||||
populate(snapshots, IslandWorld.Normal);
|
||||
if (hasNether) populate(snapshots, IslandWorld.Nether);
|
||||
if (hasEnd) populate(snapshots, IslandWorld.End);
|
||||
|
||||
BlockScanner.startScanner(snapshots, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.blocksSize = blocks.size();
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
if (skyblock.isPaper() && Bukkit.spigot().getPaperConfig().getBoolean("settings.async-chunks.enable", false)) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
populate(snapshots, IslandWorld.Normal, true);
|
||||
if (hasNether) populate(snapshots, IslandWorld.Nether, true);
|
||||
if (hasEnd) populate(snapshots, IslandWorld.End, true);
|
||||
|
||||
BlockScanner.startScanner(snapshots, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.blocksSize = blocks.size();
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
|
||||
});
|
||||
});
|
||||
} else {
|
||||
populate(snapshots, IslandWorld.Normal, false);
|
||||
if (hasNether) populate(snapshots, IslandWorld.Nether, false);
|
||||
if (hasEnd) populate(snapshots, IslandWorld.End, false);
|
||||
|
||||
BlockScanner.startScanner(snapshots, (blocks) -> {
|
||||
this.blocks = blocks;
|
||||
this.blocksSize = blocks.size();
|
||||
this.runTaskTimer(SkyBlock.getInstance(), 20, 20);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -133,37 +151,49 @@ public final class IslandScan extends BukkitRunnable {
|
|||
SkyBlock.getInstance().getLevellingManager().stopScan(island);
|
||||
}
|
||||
|
||||
if (language.getBoolean("Command.Island.Level.Scanning.Progress.Should-Display-Message") && executions == 1 || totalScanned == blocksSize || executions % runEveryX == 0) {
|
||||
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;
|
||||
final double percent = ((double) totalScanned / (double) blocksSize) * 100;
|
||||
|
||||
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));
|
||||
message = message.replace("%percent_whole%", String.valueOf((int) percent));
|
||||
message = message.replace("%percent%", FORMATTER.format(percent));
|
||||
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));
|
||||
message = message.replace("%percent_whole%", String.valueOf((int) percent));
|
||||
message = message.replace("%percent%", FORMATTER.format(percent));
|
||||
|
||||
final boolean displayComplete = totalScanned == blocksSize && language.getBoolean("Command.Island.Level.Scanning.Finished.Should-Display-Message");
|
||||
final MessageManager messageManager = SkyBlock.getInstance().getMessageManager();
|
||||
final boolean displayComplete = totalScanned == blocksSize && language.getBoolean("Command.Island.Level.Scanning.Finished.Should-Display-Message");
|
||||
final MessageManager messageManager = SkyBlock.getInstance().getMessageManager();
|
||||
|
||||
for (Player player : SkyBlock.getInstance().getIslandManager().getPlayersAtIsland(island)) {
|
||||
for (Player player : SkyBlock.getInstance().getIslandManager().getPlayersAtIsland(island)) {
|
||||
|
||||
messageManager.sendMessage(player, message);
|
||||
if (displayComplete)
|
||||
messageManager.sendMessage(player, language.getString("Command.Island.Level.Scanning.Finished.Message"));
|
||||
messageManager.sendMessage(player, message);
|
||||
if (displayComplete)
|
||||
messageManager.sendMessage(player, language.getString("Command.Island.Level.Scanning.Finished.Message"));
|
||||
|
||||
// Check for level ups
|
||||
island.getLevel().checkLevelUp();
|
||||
// Check for level ups
|
||||
island.getLevel().checkLevelUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void populate(Map<World, List<ChunkSnapshot>> snapshots, IslandWorld world) {
|
||||
private void populate(Map<World, List<ChunkSnapshot>> snapshots, IslandWorld world, boolean paper) {
|
||||
|
||||
final SkyBlock skyblock = SkyBlock.getInstance();
|
||||
|
||||
snapshots.put(skyblock.getWorldManager().getWorld(world), ChunkUtil.getChunksToScan(island, world).stream().map(org.bukkit.Chunk::getChunkSnapshot).collect(Collectors.toList()));
|
||||
ChunkUtil chunks = new ChunkUtil();
|
||||
chunks.getChunksToScan(island, world, paper);
|
||||
|
||||
if(paper){
|
||||
List<Chunk> positions = new LinkedList<>();
|
||||
for(CompletableFuture<Chunk> chunk : chunks.asyncPositions){
|
||||
positions.add(chunk.join());
|
||||
snapshots.put(skyblock.getWorldManager().getWorld(world), positions.stream().map(org.bukkit.Chunk::getChunkSnapshot).collect(Collectors.toList()));
|
||||
}
|
||||
} else {
|
||||
snapshots.put(skyblock.getWorldManager().getWorld(world), chunks.syncPositions.stream().map(org.bukkit.Chunk::getChunkSnapshot).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Location> getDoubleBlocks() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user