Files
blockandseek/src/main/java/hdvtdev/blockandseek/managers/WorldManager.java

116 lines
3.8 KiB
Java

package hdvtdev.blockAndSeek.managers;
import hdvtdev.blockAndSeek.BlockAndSeek;
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.scheduler.BukkitRunnable;
import org.codehaus.plexus.util.FileUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
@ApiStatus.Experimental
public final class WorldManager {
private static final File serverFolder = BlockAndSeek.getServerDataFolder();
private static final AsyncScheduler asyncScheduler = Bukkit.getAsyncScheduler();
private static final ConcurrentHashMap<String, WorldManager> worldManagers = new ConcurrentHashMap<>();
static {
//TODO
}
private final File originalWorld;
private final ConcurrentLinkedQueue<World> freeCopies = new ConcurrentLinkedQueue<>();
private final AtomicInteger copyIndex = new AtomicInteger(1);
private final int reservedCopies;
private WorldManager(String worldName, int reservedCopies) {
this.originalWorld = new File(serverFolder, worldName + "_copy");
this.reservedCopies = reservedCopies;
new BukkitRunnable() {
boolean unloading = false;
@Override
public void run() {
if (!Bukkit.isTickingWorlds() && !unloading) {
unloading = true;
Bukkit.unloadWorld(worldName, true);
asyncScheduler.runNow(BlockAndSeek.getInstance(), task -> {
try {
FileUtils.copyDirectoryStructure(new File(serverFolder, worldName), originalWorld);
createCopy();
} catch (IOException e) {
BlockAndSeek.getPluginLogger().severe("Failed to copy world \"" + worldName + "\": " + e.getMessage());
this.cancel();
}
});
this.cancel();
}
}
}.runTaskTimer(BlockAndSeek.getInstance(), 0, 1);
}
public static void createWorldManager(String existingWorld, int reservedCopies) {
worldManagers.put(existingWorld, new WorldManager(existingWorld, reservedCopies));
}
public static @Nullable WorldManager get(String worldName) {
return worldManagers.get(worldName);
}
/**
* @return {@link World} if a free copy is available or a new one has been created.
* Returns {@code null} if there are currently no free copies and a new copy is still being created.
*/
public @Nullable World acquire() {
if (freeCopies.size() <= 1) {
createCopy(); //TODO
}
return freeCopies.poll();
}
public void release() {
}
private void createCopy() {
String worldName = originalWorld.getName() + copyIndex.incrementAndGet();
try {
File worldCopy = new File(serverFolder, worldName);
if (!worldCopy.exists()) copyDirectoryToDirectory(originalWorld, worldCopy);
freeCopies.add(Bukkit.createWorld(WorldCreator.name(worldName)));
} catch (IOException e) {
BlockAndSeek.getPluginLogger().severe("Failed to copy world \"" + worldName + "\": " + e.getMessage());
}
}
private static void copyDirectoryToDirectory(File source, File destination) throws IOException {
File finalDestination = new File(destination, source.getName());
finalDestination.mkdirs();
FileUtils.copyDirectory(source, finalDestination);
}
}