Newer
Older
ChallengesJoinEntities / src / main / java / de / fanta / challengesjoinentities / commands / AdventureCommand / AdventureConvertMapCommand.java
@fanta fanta on 3 Apr 2023 10 KB Folia Support
package de.fanta.challengesjoinentities.commands.AdventureCommand;

import de.fanta.challengesjoinentities.ChallengesJoinEntities;
import de.fanta.challengesjoinentities.ChatUtil;
import de.iani.cubesideutils.bukkit.commands.SubCommand;
import de.iani.cubesideutils.commands.ArgsParser;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class AdventureConvertMapCommand extends SubCommand {
    private static FileConfiguration ServerConfig;
    private static File ServerConfigFile;
    private static ChallengesJoinEntities plugin;

    public AdventureConvertMapCommand(ChallengesJoinEntities plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String s, String s1, ArgsParser args) {
        String urlString;
        String versioString;

        if (!(sender instanceof Player player)) {
            ChatUtil.sendErrorMessage(sender, "You are not a Player");
            return true;
        }

        if (!player.hasPermission("adventure.convertmap")) {
            ChatUtil.sendErrorMessage(player, "Keine Rechte!");
            return true;
        }

        if (args.hasNext()) {
            urlString = args.getNext();
            if (args.hasNext()) {
                versioString = args.getNext();
            } else {
                ChatUtil.sendErrorMessage(player, "/convertmap <URL> <Server-Version>");
                return true;
            }

            File folder = new File(Bukkit.getPluginsFolder().getPath() + "/Challenges/MapConverter");

            if (!folder.exists()) {
                folder.mkdir();
            }

            String finalUrlString = urlString;
            String finalVersioString = versioString;
            plugin.getScheduler().runAsync(() -> downloadMap(finalUrlString, finalVersioString, folder, player));
        } else {
            ChatUtil.sendErrorMessage(sender, "/convertmap <URL> <Server-Version>");
            return true;
        }
        return true;
    }

    private static void downloadMap(String finalUrlString, String versioString, File folder, Player player) {
        Path zipPath = Path.of(folder + "/world.zip");
        try {
            InputStream in = new URL(finalUrlString).openStream();
            Files.copy(in, zipPath, StandardCopyOption.REPLACE_EXISTING);
            ChatUtil.sendNormalMessage(player, "Map heruntergeladen.");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        unZip(folder, zipPath, versioString, player);
    }


    private static void unZip(File folder, Path zipPath, String versioString, Player player) {
        File worldFolder = new File(folder.getPath() + "/" + UUID.randomUUID());
        try {
            unzipFolder(zipPath, worldFolder.toPath());
            ChatUtil.sendNormalMessage(player, "UnZip Done " + worldFolder.getName());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        searchRegionFile(worldFolder, versioString, player);
    }

    private static void searchRegionFile(File file, String versioString, Player player) {
        File[] files;
        files = file.listFiles();
        if (files != null) {
            for (File filefile : files) {
                if (filefile.getName().equals("region")) {
                    ChatUtil.sendNormalMessage(player, "region folder found");
                    convertToSpigotMap(filefile.getAbsoluteFile(), versioString, player);
                    return;
                }

                if (filefile.isDirectory()) {
                    searchRegionFile(filefile, versioString, player);
                }
            }
        }
    }

    private static void convertToSpigotMap(File file, String versioString, Player player) {
        if (file != null) {
            File mapFolder = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 7));
            File worldFolder = new File(mapFolder.getAbsoluteFile() + "/world");
            File netherFolder = new File(mapFolder.getAbsoluteFile() + "/world_nether");
            File endFolder = new File(mapFolder.getAbsoluteFile() + "/world_the_end");

            try {
                FileUtils.forceMkdir(worldFolder);
                FileUtils.forceMkdir(netherFolder);
                FileUtils.forceMkdir(endFolder);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            File[] files;
            files = mapFolder.listFiles();
            if (files != null) {
                for (File tempFiles : files) {
                    try {
                        if (!tempFiles.getName().equals("DIM1") && !tempFiles.getName().equals("DIM-1") && !tempFiles.getName().equals("world") && !tempFiles.getName().equals("world_nether") && !tempFiles.getName().equals("world_the_end")) {
                            if (tempFiles.isDirectory()) {
                                FileUtils.moveDirectory(tempFiles, new File(worldFolder + "/" + tempFiles.getName()));
                            } else {
                                FileUtils.moveFile(tempFiles, new File(worldFolder + "/" + tempFiles.getName()));
                            }
                        }

                        if (tempFiles.getName().equals("DIM1")) {
                            FileUtils.moveDirectory(tempFiles, new File(endFolder + "/" + tempFiles.getName()));
                        }

                        if (tempFiles.getName().equals("DIM-1")) {
                            FileUtils.moveDirectory(tempFiles, new File(netherFolder + "/" + tempFiles.getName()));
                        }
                    } catch (IOException e) {
                        plugin.getLogger().log(Level.SEVERE, "Can't Copy File", e);
                    }
                }

                File challengesFolder = new File(mapFolder.getAbsoluteFile() + "/Challenges");

                try {
                    FileUtils.forceMkdir(challengesFolder);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

                createServerConfig(challengesFolder);


                try {
                    getServerConfig().set("servertype", "ADVENTURE");
                    ServerConfig.save(ServerConfigFile);
                    getServerConfig().set("serverversion", versioString);
                    ServerConfig.save(ServerConfigFile);
                } catch (IOException e) {
                    Bukkit.getLogger().log(Level.SEVERE, "Can't Save Config", e);
                }

                String oldFolderName = mapFolder.getName();
                String newFolderName = mapFolder.getName().replace(" ", "_");
                File newFolderFile = new File(mapFolder.getPath().replace(oldFolderName, newFolderName));

                mapFolder.renameTo(newFolderFile);

                ChatUtil.sendNormalMessage(player, "Konvertierung fertig.");

                File destFolder = new File("/home/minecraft/Adventure-Maps/test/" + newFolderName);

                try {
                    FileUtils.moveDirectory(newFolderFile, destFolder);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

                ChatUtil.sendNormalMessage(player, "Map wurde zum testen in das test Verzeichnis verschoben.");

                TextComponent component = new TextComponent(TextComponent.fromLegacyText(ChallengesJoinEntities.PREFIX + ChatUtil.GREEN + " Klicke hier um die Map zu testen."));
                component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/a testmap test " + newFolderName));
                player.sendMessage(component);

            } else {
                ChatUtil.sendErrorMessage(player, "Keine datei gefunden.");
            }

        } else {
            ChatUtil.sendErrorMessage(player, "Keine datei gefunden.");
        }
    }

    public static FileConfiguration getServerConfig() {
        return ServerConfig;
    }

    private static void createServerConfig(File folder) {
        ServerConfigFile = new File(folder.getPath() + "/serverconfig.yml");
        if (!ServerConfigFile.exists()) {
            try {
                FileUtils.forceMkdirParent(ServerConfigFile);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        ServerConfig = new YamlConfiguration();
    }

    public static void unzipFolder(Path source, Path target) throws IOException {
        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) {
            ZipEntry zipEntry = zis.getNextEntry();

            while (zipEntry != null) {

                boolean isDirectory = zipEntry.getName().endsWith(File.separator);

                Path newPath = zipSlipProtect(zipEntry, target);

                if (isDirectory) {
                    Files.createDirectories(newPath);
                } else {
                    if (newPath.getParent() != null) {
                        if (Files.notExists(newPath.getParent())) {
                            Files.createDirectories(newPath.getParent());
                        }
                    }
                    Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING);
                }
                zipEntry = zis.getNextEntry();
            }
            zis.closeEntry();
        }
    }

    public static Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException {
        Path targetDirResolved = targetDir.resolve(zipEntry.getName());
        Path normalizePath = targetDirResolved.normalize();

        if (!normalizePath.startsWith(targetDir)) {
            throw new IOException("Bad zip entry: " + zipEntry.getName());
        }

        return normalizePath;
    }
}