mirror of
https://github.com/songoda/FabledSkyBlock.git
synced 2025-01-10 09:47:42 +01:00
Segment island level scanning
This commit is contained in:
parent
c019114f29
commit
2d246d0c48
@ -1,84 +1,169 @@
|
||||
package me.goodandevil.skyblock.levelling;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import me.goodandevil.skyblock.SkyBlock;
|
||||
import me.goodandevil.skyblock.island.Island;
|
||||
import me.goodandevil.skyblock.island.IslandEnvironment;
|
||||
import me.goodandevil.skyblock.island.IslandWorld;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class Chunk {
|
||||
|
||||
private static final int MAX_CHUNKS = 150;
|
||||
private final SkyBlock skyblock;
|
||||
private Island island;
|
||||
|
||||
private List<ChunkSnapshot> chunkSnapshots = new ArrayList<>();
|
||||
private boolean complete;
|
||||
private int initialNumberOfChunks = -1;
|
||||
private Set<ChunkPosition> chunkPositions = new HashSet<>();
|
||||
private Set<ChunkSnapshot> chunkSnapshots = new HashSet<>();
|
||||
private boolean isReady = false;
|
||||
private boolean isFinished = false;
|
||||
|
||||
public Chunk(SkyBlock skyblock, Island island) {
|
||||
this.skyblock = skyblock;
|
||||
this.island = island;
|
||||
|
||||
complete = false;
|
||||
}
|
||||
|
||||
public void prepare() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
prepareChunkSnapshots();
|
||||
}
|
||||
}.runTask(skyblock);
|
||||
}
|
||||
public void prepareInitial() {
|
||||
Bukkit.getScheduler().runTask(this.skyblock, () -> {
|
||||
FileConfiguration config = this.skyblock.getFileManager().getConfig(new File(this.skyblock.getDataFolder(), "config.yml")).getFileConfiguration();
|
||||
FileConfiguration islandData = this.skyblock.getFileManager().getConfig(new File(new File(this.skyblock.getDataFolder().toString() + "/island-data"), this.island.getOwnerUUID().toString() + ".yml")).getFileConfiguration();
|
||||
|
||||
public List<ChunkSnapshot> getChunkSnapshots() {
|
||||
return chunkSnapshots;
|
||||
}
|
||||
boolean hasNether = config.getBoolean("Island.World.Nether.Enable") && islandData.getBoolean("Unlocked.Nether", false);
|
||||
boolean hasEnd = config.getBoolean("Island.World.End.Enable") && islandData.getBoolean("Unlocked.End", false);
|
||||
|
||||
public boolean isComplete() {
|
||||
return complete;
|
||||
}
|
||||
|
||||
private void prepareChunkSnapshots() {
|
||||
FileConfiguration config = skyblock.getFileManager().getConfig(new File(skyblock.getDataFolder(), "config.yml")).getFileConfiguration();
|
||||
FileConfiguration islandData = skyblock.getFileManager().getConfig(new File(new File(skyblock.getDataFolder().toString() + "/island-data"), island.getOwnerUUID().toString() + ".yml")).getFileConfiguration();
|
||||
boolean hasNormal = true;
|
||||
boolean hasNether = config.getBoolean("Island.World.Nether.Enable") && islandData.getBoolean("Unlocked.Nether", false);
|
||||
boolean hasEnd = config.getBoolean("Island.World.End.Enable") && islandData.getBoolean("Unlocked.End", false);
|
||||
|
||||
for (IslandWorld iWorld : IslandWorld.values()) {
|
||||
if ((iWorld == IslandWorld.Normal && hasNormal) || (iWorld == IslandWorld.Nether && hasNether) || (iWorld == IslandWorld.End && hasEnd)) {
|
||||
Location islandLocation = island.getLocation(iWorld, IslandEnvironment.Island);
|
||||
|
||||
Location minLocation = new Location(islandLocation.getWorld(),
|
||||
islandLocation.getBlockX() - island.getRadius(), 0,
|
||||
islandLocation.getBlockZ() - island.getRadius());
|
||||
Location maxLocation = new Location(islandLocation.getWorld(),
|
||||
islandLocation.getBlockX() + island.getRadius(), islandLocation.getWorld().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());
|
||||
|
||||
for (int x = MinX - 16; x <= MaxX + 16; x += 16) {
|
||||
for (int z = MinZ - 16; z <= MaxZ + 16; z += 16) {
|
||||
org.bukkit.Chunk chunk = islandLocation.getWorld().getBlockAt(x, 0, z).getChunk();
|
||||
chunkSnapshots.add(chunk.getChunkSnapshot());
|
||||
}
|
||||
for (IslandWorld islandWorld : IslandWorld.values()) {
|
||||
if (islandWorld == IslandWorld.Normal || (islandWorld == IslandWorld.Nether && hasNether) || (islandWorld == IslandWorld.End && hasEnd)) {
|
||||
this.getChunksToScan(islandWorld);
|
||||
}
|
||||
}
|
||||
|
||||
this.initialNumberOfChunks = this.chunkPositions.size();
|
||||
|
||||
this.prepareNextChunkSnapshots();
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isReadyToScan() {
|
||||
return this.isReady;
|
||||
}
|
||||
|
||||
public Set<ChunkSnapshot> getAvailableChunkSnapshots() {
|
||||
this.isReady = false;
|
||||
return this.chunkSnapshots;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return this.isFinished;
|
||||
}
|
||||
|
||||
public void prepareNextChunkSnapshots() {
|
||||
Bukkit.getScheduler().runTask(this.skyblock, () -> {
|
||||
this.chunkSnapshots.clear();
|
||||
|
||||
Iterator<ChunkPosition> it = this.chunkPositions.iterator();
|
||||
if (!it.hasNext()) {
|
||||
this.isReady = true;
|
||||
this.isFinished = true;
|
||||
this.sendFinishedMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
int percentComplete = (int)((1 - ((double)this.chunkPositions.size() / this.initialNumberOfChunks)) * 100);
|
||||
this.sendPercentMessage(percentComplete);
|
||||
|
||||
while (it.hasNext() && this.chunkSnapshots.size() < MAX_CHUNKS) {
|
||||
ChunkPosition chunkPosition = it.next();
|
||||
World world = chunkPosition.getWorld();
|
||||
int x = chunkPosition.getX();
|
||||
int z = chunkPosition.getZ();
|
||||
if (!world.isChunkLoaded(x, z)) {
|
||||
world.loadChunk(x, z);
|
||||
this.chunkSnapshots.add(world.getChunkAt(x, z).getChunkSnapshot());
|
||||
world.unloadChunk(x, z);
|
||||
} else {
|
||||
this.chunkSnapshots.add(world.getChunkAt(x, z).getChunkSnapshot());
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
|
||||
this.isReady = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void sendPercentMessage(int percent) {
|
||||
String message = ChatColor.translateAlternateColorCodes('&',
|
||||
this.skyblock.getFileManager()
|
||||
.getConfig(new File(this.skyblock.getDataFolder(), "language.yml"))
|
||||
.getFileConfiguration().getString("Command.Island.Level.Scanning.Progress.Message")
|
||||
.replace("%percent", String.valueOf(percent)));
|
||||
for (Player player : this.skyblock.getIslandManager().getPlayersAtIsland(this.island)) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendFinishedMessage() {
|
||||
String message = ChatColor.translateAlternateColorCodes('&', this.skyblock.getFileManager()
|
||||
.getConfig(new File(this.skyblock.getDataFolder(), "language.yml"))
|
||||
.getFileConfiguration().getString("Command.Island.Level.Scanning.Finished.Message"));
|
||||
for (Player player : this.skyblock.getIslandManager().getPlayersAtIsland(this.island)) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
|
||||
}
|
||||
}
|
||||
|
||||
private void getChunksToScan(IslandWorld islandWorld) {
|
||||
Location islandLocation = this.island.getLocation(islandWorld, IslandEnvironment.Island);
|
||||
World world = islandLocation.getWorld();
|
||||
|
||||
Location minLocation = new Location(world, islandLocation.getBlockX() - this.island.getRadius(), 0, islandLocation.getBlockZ() - this.island.getRadius());
|
||||
Location maxLocation = new Location(world, islandLocation.getBlockX() + this.island.getRadius(), world.getMaxHeight(), islandLocation.getBlockZ() + this.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());
|
||||
|
||||
for (int x = minX; x < maxX + 16; x += 16) {
|
||||
for (int z = minZ; z < maxZ + 16; z += 16) {
|
||||
this.chunkPositions.add(new ChunkPosition(world, x >> 4, z >> 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ChunkPosition {
|
||||
private World world;
|
||||
private int x, z;
|
||||
|
||||
public ChunkPosition(World world, int x, int z) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
complete = true;
|
||||
public World getWorld() {
|
||||
return this.world;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,37 +42,44 @@ public class LevellingManager {
|
||||
StackableManager stackableManager = skyblock.getStackableManager();
|
||||
|
||||
Chunk chunk = new Chunk(skyblock, island);
|
||||
chunk.prepare();
|
||||
chunk.prepareInitial();
|
||||
|
||||
int NMSVersion = NMSUtil.getVersionNumber();
|
||||
|
||||
int height = 0;
|
||||
|
||||
for (IslandWorld worldList : IslandWorld.values()) {
|
||||
org.bukkit.World world = worldManager.getWorld(worldList);
|
||||
|
||||
if (height == 0 || height > world.getMaxHeight()) {
|
||||
height = world.getMaxHeight();
|
||||
}
|
||||
}
|
||||
|
||||
int worldMaxHeight = height;
|
||||
|
||||
boolean isEpicSpawnersEnabled = Bukkit.getPluginManager().isPluginEnabled("EpicSpawners");
|
||||
boolean isWildStackerEnabled = Bukkit.getPluginManager().isPluginEnabled("WildStacker");
|
||||
|
||||
Map<LevellingData, Long> levellingData = new HashMap<>();
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!chunk.isComplete()) return;
|
||||
cancel();
|
||||
if (!chunk.isReadyToScan()) return;
|
||||
|
||||
if (chunk.isFinished()) {
|
||||
finalizeMaterials(levellingData, player, island);
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
Method getBlockTypeMethod = null;
|
||||
Method getBlockTypeIdMethod = null;
|
||||
Method getBlockTypeDataMethod = null;
|
||||
Method getMaterialMethod = null;
|
||||
|
||||
int worldMaxHeight = 0;
|
||||
|
||||
for (IslandWorld worldList : IslandWorld.values()) {
|
||||
org.bukkit.World world = worldManager.getWorld(worldList);
|
||||
|
||||
if (worldMaxHeight == 0 || worldMaxHeight > world.getMaxHeight()) {
|
||||
worldMaxHeight = world.getMaxHeight();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isEpicSpawnersEnabled = Bukkit.getPluginManager().isPluginEnabled("EpicSpawners");
|
||||
boolean isWildStackerEnabled = Bukkit.getPluginManager().isPluginEnabled("WildStacker");
|
||||
|
||||
Map<LevellingData, Long> levellingData = new HashMap<>();
|
||||
|
||||
for (ChunkSnapshot chunkSnapshotList : chunk.getChunkSnapshots()) {
|
||||
for (ChunkSnapshot chunkSnapshotList : chunk.getAvailableChunkSnapshots()) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < worldMaxHeight; y++) {
|
||||
@ -175,38 +182,42 @@ public class LevellingManager {
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Long> materials = new HashMap<>();
|
||||
for (LevellingData data : levellingData.keySet()) {
|
||||
long amount = levellingData.get(data);
|
||||
if (data.getMaterials() != null) {
|
||||
materials.put(data.getMaterials().name(), amount);
|
||||
}
|
||||
}
|
||||
|
||||
if (materials.size() == 0) {
|
||||
if (player != null) {
|
||||
skyblock.getMessageManager().sendMessage(player, skyblock.getFileManager()
|
||||
.getConfig(new File(skyblock.getDataFolder(), "language.yml"))
|
||||
.getFileConfiguration().getString("Command.Island.Level.Materials.Message"));
|
||||
skyblock.getSoundManager().playSound(player, Sounds.VILLAGER_NO.bukkitSound(), 1.0F, 1.0F);
|
||||
}
|
||||
} else {
|
||||
IslandLevel level = island.getLevel();
|
||||
level.setLastCalculatedPoints(level.getPoints());
|
||||
level.setLastCalculatedLevel(level.getLevel());
|
||||
level.setMaterials(materials);
|
||||
|
||||
Bukkit.getServer().getPluginManager().callEvent(
|
||||
new IslandLevelChangeEvent(island.getAPIWrapper(), island.getAPIWrapper().getLevel()));
|
||||
|
||||
if (player != null) {
|
||||
me.goodandevil.skyblock.menus.Levelling.getInstance().open(player);
|
||||
}
|
||||
}
|
||||
chunk.prepareNextChunkSnapshots();
|
||||
}
|
||||
}.runTaskTimerAsynchronously(skyblock, 0L, 1L);
|
||||
}
|
||||
|
||||
private void finalizeMaterials(Map<LevellingData, Long> levellingData, Player player, Island island) {
|
||||
Map<String, Long> materials = new HashMap<>();
|
||||
for (LevellingData data : levellingData.keySet()) {
|
||||
long amount = levellingData.get(data);
|
||||
if (data.getMaterials() != null) {
|
||||
materials.put(data.getMaterials().name(), amount);
|
||||
}
|
||||
}
|
||||
|
||||
if (materials.size() == 0) {
|
||||
if (player != null) {
|
||||
skyblock.getMessageManager().sendMessage(player, skyblock.getFileManager()
|
||||
.getConfig(new File(skyblock.getDataFolder(), "language.yml"))
|
||||
.getFileConfiguration().getString("Command.Island.Level.Materials.Message"));
|
||||
skyblock.getSoundManager().playSound(player, Sounds.VILLAGER_NO.bukkitSound(), 1.0F, 1.0F);
|
||||
}
|
||||
} else {
|
||||
IslandLevel level = island.getLevel();
|
||||
level.setLastCalculatedPoints(level.getPoints());
|
||||
level.setLastCalculatedLevel(level.getLevel());
|
||||
level.setMaterials(materials);
|
||||
|
||||
Bukkit.getServer().getPluginManager().callEvent(
|
||||
new IslandLevelChangeEvent(island.getAPIWrapper(), island.getAPIWrapper().getLevel()));
|
||||
|
||||
if (player != null) {
|
||||
me.goodandevil.skyblock.menus.Levelling.getInstance().open(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerMaterials() {
|
||||
Config config = skyblock.getFileManager().getConfig(new File(skyblock.getDataFolder(), "levelling.yml"));
|
||||
FileConfiguration configLoad = config.getFileConfiguration();
|
||||
|
@ -458,6 +458,11 @@ Command:
|
||||
Message: "&bSkyBlock &8| &aInfo&8: &7&oProcessing Island level request... Please wait!"
|
||||
Loading:
|
||||
Message: "&bSkyBlock &8| &aInfo&8: &7&oLoading Island Materials... Please wait!"
|
||||
Scanning:
|
||||
Progress:
|
||||
Message: "&eScanning island level: &b%percent%"
|
||||
Finished:
|
||||
Message: "&aIsland level scan complete!"
|
||||
Owner:
|
||||
Yourself:
|
||||
Message: "&bSkyBlock &8| &cError&8: &eYou are not an Island owner."
|
||||
|
Loading…
Reference in New Issue
Block a user