116 lines
3.8 KiB
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);
|
|
}
|
|
|
|
}
|