package de.fanta.challengesjoinentities;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
public class Server {
public static HashMap<Server, UUID> serverPlayers = new HashMap<>();
private final ChallengesJoinEntities plugin;
private final String name;
private int serverVersion;
private final String gPLocation;
private final String dir;
private final ServerType serverType;
private final Location piglinLocation;
private boolean online;
public Server(String name, @Nullable Integer serverVersion, String gPLocation, String dir, ServerType serverType, ChallengesJoinEntities plugin, Location piglinLocation) {
this.name = name;
this.serverVersion = serverVersion == null ? 0 : serverVersion;
this.gPLocation = gPLocation;
this.dir = dir;
this.serverType = serverType;
this.plugin = plugin;
this.online = (plugin.getGlobalDataHelper().getServer(name) != null);
this.piglinLocation = piglinLocation;
}
public static Server getServerfromPlayer(Player p) {
Server server = null;
if (serverPlayers.containsValue(p.getUniqueId()))
for (Map.Entry<Server, UUID> entry : serverPlayers.entrySet()) {
if (entry.getValue().equals(p.getUniqueId()))
server = entry.getKey();
}
return server;
}
public boolean isOnline() {
return this.online;
}
public void setOnline(boolean online) {
this.online = online;
}
public String getName() {
return this.name;
}
public String getGPLocation() {
return this.gPLocation;
}
public void setServerVersion(int serverVersion) {
this.serverVersion = serverVersion;
}
public void loadSaved(Player p, UUID playerID, String slot) {
this.online = true;
serverPlayers.put(this, p.getUniqueId());
File dir;
//dir = new File("/home/minecraft/" + this.serverType.getDir() + "/" + playerID + "/" + slot);
if (serverType == ServerType.CHALLENGES) {
dir = new File(plugin.getChallengeSavePath().toFile(), "/" + playerID + "/" + slot);
} else {
dir = new File(plugin.getAdventureSavePath().toFile(), "/" + playerID + "/" + slot);
}
String path = playerID + "/" + slot;
if (!dir.isDirectory()) {
ChatUtil.sendErrorMessage(p, "Map " + path + " nicht gefunden!");
this.online = false;
serverPlayers.remove(this);
return;
}
load(p, this.serverType.getDir(), path, getMapVersion(new File(dir + "/Challenges/serverconfig.yml")));
}
public void loadNewAdventure(Player player, String category, String map, String mapVersion) {
int playerVersion = Via.getAPI().getPlayerVersion(player.getUniqueId());
int mapProtocolVersion = ProtocolVersion.getClosest(mapVersion).getVersion();
if (playerVersion >= mapProtocolVersion) {
this.online = true;
serverPlayers.put(this, player.getUniqueId());
//File dir = new File("/home/storagebox/Adventure-Maps", category + "/" + map);
File dir = new File(plugin.getAdventureMapsPath().toFile(), category + "/" + map);
if (!dir.isDirectory()) {
ChatUtil.sendErrorMessage(player, "Map " + map + " nicht gefunden!");
this.online = false;
serverPlayers.remove(this);
return;
}
load(player, "Adventure-Maps", category + "/" + map, getMapVersion(new File(dir + "/Challenges/serverconfig.yml")));
} else {
ChatUtil.sendErrorMessage(player, "Du brauchst mindestens die Version " + ChatUtil.BLUE + mapVersion + ChatUtil.RED + " um die Map zu starten!");
}
}
public void load(Player p, String serverTypeDir, String targetDir, String ServerVersion) {
plugin.getScheduler().runAsync(() -> {
File serverFolder = new File(plugin.getServerFolderPath().toFile(), this.dir);
File configs = new File(serverFolder, "/plugins/Challenges");
File end = new File(serverFolder, "/world_the_end");
File nether = new File(serverFolder, "/world_nether");
File world = new File(serverFolder, "/world");
File mlgworld = new File(serverFolder, "/mlg_challenge");
File serverJar = new File(serverFolder, "/paper.jar");
File saveServerJar = new File(plugin.getServerJarsPath().toFile(), ServerVersion + "/paper.jar");
File saveend;
File savenether;
File saveworld;
File saveconfigs;
if (!serverTypeDir.equals("Adventure-Maps")) {
saveend = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/world_the_end");
savenether = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/world_nether");
saveworld = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/world");
saveconfigs = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/Challenges");
} else {
saveend = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/world_the_end");
savenether = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/world_nether");
saveworld = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/world");
saveconfigs = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/Challenges");
}
ChatUtil.sendNormalMessage(p, "Versuche Map zu laden!");
try {
if (world.isDirectory()) {
FileUtils.deleteDirectory(world);
FileUtils.deleteDirectory(end);
FileUtils.deleteDirectory(nether);
}
if (mlgworld.isDirectory()) {
FileUtils.deleteDirectory(mlgworld);
}
if (serverJar.exists()) {
FileUtils.delete(serverJar);
}
if (configs.isDirectory()) {
FileUtils.deleteDirectory(configs);
}
HashMap<File, File> copyMap = new HashMap<>();
copyMap.put(saveServerJar, serverJar);
copyMap.put(saveconfigs, configs);
copyMap.put(saveworld, world);
copyMap.put(savenether, nether);
copyMap.put(saveend, end);
moveFolderWithProgress(copyMap, p);
File serverConfigFile = new File(plugin.getServerFolderPath().toFile(), this.dir + "/plugins/Challenges/serverconfig.yml");
YamlConfiguration serverConfig = new YamlConfiguration();
serverConfig.load(serverConfigFile);
String tempServerType = serverConfig.getString("servertype");
if (tempServerType == null || tempServerType.equals("CHALLENGE")) {
serverConfig.set("servertype", "CHALLENGE_LOAD");
serverConfig.save(serverConfigFile);
Bukkit.getLogger().info(serverConfigFile.getAbsolutePath());
}
if (tempServerType != null && serverConfig.getString("servertype").equals("ADVENTURE")) {
setServerVersion(ProtocolVersion.getClosest(serverConfig.getString("serverversion")).getVersion());
}
} catch (IOException | InvalidConfigurationException e) {
e.printStackTrace();
ChatUtil.sendErrorMessage(p, "Map konnte nicht geladen werden!");
this.online = false;
serverPlayers.remove(this);
return;
}
ChatUtil.sendNormalMessage(p, "Map wurde geladen! Server wird nun gestartet!");
start(p);
});
}
public static void moveFolderWithProgress(HashMap<File, File> copyMap, Player player) throws IOException {
final long[] totalBytes = {0};
final long[] copiedBytes = {0};
AtomicReference<Double> progress = new AtomicReference<>(0.0);
for (File sourceFolder : copyMap.keySet()) {
Files.walk(sourceFolder.toPath()).forEach(source -> {
if (!Files.isDirectory(source)) {
totalBytes[0] += source.toFile().length();
}
});
}
for (File sourceFolder : copyMap.keySet()) {
Files.walk(sourceFolder.toPath()).forEach(source -> {
try {
File target = new File(copyMap.get(sourceFolder).toPath().resolve(sourceFolder.toPath().relativize(source)).toString());
if (Files.isDirectory(source)) {
target.mkdir();
} else {
Files.copy(source, target.toPath(), StandardCopyOption.REPLACE_EXISTING);
copiedBytes[0] += source.toFile().length();
progress.set((double) copiedBytes[0] / totalBytes[0] * 100);
player.sendActionBar(ChatUtil.GREEN + "Kopiere Welt: " + getProgressBar(progress.get()));
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
public static String getProgressBar(double value) {
int progress = (int) (value / 100 * 40);
StringBuilder progressBar = new StringBuilder();
progressBar.append(ChatUtil.RED + "[");
for (int i = 0; i < 40; i++) {
if (i < progress) {
progressBar.append(ChatUtil.PINK + "|");
} else {
progressBar.append(ChatUtil.GREEN + "|");
}
}
progressBar.append(ChatUtil.RED + "] " + ChatUtil.PINK + String.format("%.2f", value) + "%");
return progressBar.toString();
}
public void start(Player player) {
ProcessBuilder processBuilder = new ProcessBuilder();
boolean eventServer = false;
if (this.serverType == ServerType.ADVENTURE && plugin.getEventServerPlayerList().contains(player.getUniqueId())) {
//processBuilder.command("screen", "-AmdS", player.getName(), "./event.sh").directory(new File("/home/minecraft/Server/" + this.dir));
processBuilder.command("screen", "-AmdS", player.getName(), "./event.sh").directory(new File(plugin.getServerFolderPath().toFile(), this.dir));
plugin.getEventServerPlayerList().remove(player.getUniqueId());
eventServer = true;
} else {
//processBuilder.command("screen", "-AmdS", player.getName(), "./start.sh").directory(new File("/home/minecraft/Server/" + this.dir));
processBuilder.command("screen", "-AmdS", player.getName(), "./start.sh").directory(new File(plugin.getServerFolderPath().toFile(), this.dir));
}
try {
processBuilder.start();
Bukkit.getLogger().info(this.serverType.toString().toLowerCase() + (eventServer ? " Event Server: " : " Server: ") + getServerfromPlayer(player).gPLocation + " wurde von " + player.getName() + " gestartet!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void spawnPiglin(Player player) {
this.plugin.spawnPiglin(this.piglinLocation, this.name, this.serverVersion, this.gPLocation, player.getName(), false);
}
public void despawnPiglin() {
this.plugin.despawnPiglin(this.name);
}
public void spawnNPC(Player player) {
this.plugin.spawnNPC(this.piglinLocation, this.name, this.gPLocation, player.getName(), false);
}
public void despawnNPC() {
this.plugin.despawnNPC(this.name);
}
public String getMapVersion(File config) {
String serverVersion;
YamlConfiguration serverConfiguration = new YamlConfiguration();
if (!config.exists()) {
serverVersion = "latest";
return serverVersion;
}
try {
serverConfiguration.load(config);
} catch (IOException | org.bukkit.configuration.InvalidConfigurationException e) {
e.printStackTrace();
}
String configServerVersion = serverConfiguration.getString("serverversion");
if (configServerVersion != null) {
File serverversionfolder = new File(plugin.getServerJarsPath().toFile(), configServerVersion);
if (serverversionfolder.isDirectory()) {
serverVersion = configServerVersion;
} else {
serverVersion = "latest";
}
} else {
serverVersion = "latest";
}
return serverVersion;
}
}