package de.fanta.challenges.utils;
import de.cubeside.nmsutils.NMSUtils;
import de.fanta.challenges.Challenges;
import de.fanta.challenges.SaveSlot;
import de.fanta.challenges.ServerType;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
public class SaveWorldUtils {
private static final Challenges plugin = Challenges.getPlugin();
public static void saveWorld(String saveID, SaveSlot saveSlot) {
saveWorld(null, saveID, saveSlot);
}
public static void saveWorld(@Nullable Player player, String saveID, SaveSlot saveSlot) {
try {
if (plugin.getServerType() == ServerType.CHALLENGE_EVENT) {
if (player != null) {
ChatUtil.sendErrorMessage(player, "Challenge Events können nicht gespeichert werden.");
}
return;
}
Challenges.getPlugin().getConfig().set("timertime", Challenges.getPlugin().getTimer().getTime());
Challenges.getPlugin().saveConfig();
Challenges.getPlugin().getConfig().set("backpack_size", Challenges.getPlugin().getBackpack().getSize() / 9);
Challenges.getPlugin().saveConfig();
Challenges.getPlugin().getBackpack().saveInventoryToConfig();
World world_world = Bukkit.getWorlds().get(0);
World world_nether = Bukkit.getWorlds().get(1);
World world_end = Bukkit.getWorlds().get(2);
if (!plugin.isFolia()) {
world_world.save();
world_nether.save();
world_end.save();
}
for (Player p : Bukkit.getOnlinePlayers()) {
p.saveData();
}
NMSUtils nms = plugin.getNMSUtils();
if (nms != null) {
if (!plugin.isFolia()) {
nms.getWorldUtils().saveWorldNow(world_world);
nms.getWorldUtils().saveWorldNow(world_end);
nms.getWorldUtils().saveWorldNow(world_nether);
copyWorld(player, saveID, saveSlot);
} else {
ArrayList<CompletableFuture<Void>> allTasks = new ArrayList<>();
for (World world : Bukkit.getWorlds()) {
for (Chunk chunk : world.getLoadedChunks()) {
CompletableFuture<Void> future = new CompletableFuture<>();
allTasks.add(future);
Bukkit.getServer().getRegionScheduler().run(plugin, world, chunk.getX(), chunk.getZ(), scheduledTask -> {
try {
nms.getWorldUtils().saveChunkNow(chunk);
} finally {
future.complete(null);
}
});
}
}
CompletableFuture<Void> waitForAll = CompletableFuture.allOf(allTasks.toArray(new CompletableFuture[0]));
plugin.getScheduler().runAsync(() -> {
try {
waitForAll.get();
nms.getWorldUtils().flushChunkSaves();
copyWorld(player, saveID, saveSlot);
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
});
}
}
} catch (Exception ex) {
plugin.getLogger().log(Level.SEVERE, "Welt konnte nicht gespeichert werden", ex);
if (player != null) {
ChatUtil.sendErrorMessage(player, "Welt konnte nicht gespeichert werden!");
}
}
}
private static void copyWorld(Player player, String saveID, SaveSlot saveSlot) {
File dir = new File(saveID);
File configs = new File("plugins/Challenges");
File end = new File("world_the_end");
File nether = new File("world_nether");
File world = new File("world");
File saveend = new File(saveID + "/world_the_end");
File savenether = new File(saveID + "/world_nether");
File saveworld = new File(saveID + "/world");
File saveconfigs = new File(saveID + "/Challenges");
File saveFolder;
if (plugin.getServerType() != ServerType.ADVENTURE) {
saveFolder = new File("/home/minecraft/saves/" + saveID + "/" + saveSlot.getSlot() + "/");
} else {
saveFolder = new File("/home/minecraft/Adventure-saves/" + saveID + "/" + saveSlot.getSlot() + "/");
}
try {
FileUtils.forceMkdir(dir);
FileUtils.copyDirectory(configs, saveconfigs);
FileUtils.copyDirectory(end, saveend);
FileUtils.copyDirectory(nether, savenether);
FileUtils.copyDirectory(world, saveworld);
if (saveFolder.isDirectory()) {
FileUtils.deleteDirectory(saveFolder);
}
FileUtils.moveDirectory(dir, saveFolder);
} catch (IOException ex) {
Bukkit.getLogger().log(Level.SEVERE, "Could not save world ", ex);
if (player != null) {
ChatUtil.sendErrorMessage(Bukkit.getPlayer(saveID), "Map konnte nicht richtig gespeichert werden, bitte versuche es noch einmal");
}
return;
}
if (player != null) {
ChatUtil.sendNormalMessage(player, "Welt wurde erfolgreich auf Slot " + saveSlot.getSlot() + " gespeichert!");
}
}
}