com.github.hexocraft.worldrestorer.WorldRestorerApi.java Source code

Java tutorial

Introduction

Here is the source code for com.github.hexocraft.worldrestorer.WorldRestorerApi.java

Source

package com.github.hexocraft.worldrestorer;

/*
 * Copyright 2017 hexosse
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

import com.github.hexocraft.worldrestorer.configuration.WorldConfig;
import com.github.hexocraftapi.message.predifined.message.SimplePrefixedMessage;
import com.github.hexocraftapi.message.predifined.message.WarningPrefixedMessage;
import com.github.hexocraftapi.nms.utils.NmsWorldUtil;
import com.google.common.collect.Lists;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.entity.Player;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.github.hexocraft.worldrestorer.command.WrCommands.prefix;

/**
 * @author <b>hexosse</b> (<a href="https://github.comp/hexosse">hexosse on GitHub</a>))
 */
public class WorldRestorerApi {
    private static final String worldSaves = "WorldSaves";
    private static final String worldSettings = "WorldSettings.yml";

    private static List<Player> worldPlayers = null;

    // List of existing saved worlds
    public static ArrayList<String> listWorlds(JavaPlugin plugin) {
        File worldSavesFolder = new File(plugin.getDataFolder() + "/" + worldSaves + "/");
        String[] directories = worldSavesFolder.list(new FilenameFilter() {
            @Override
            public boolean accept(File file, String name) {
                if (file.isDirectory()) {
                    String[] settings = file.list(new FilenameFilter() {
                        @Override
                        public boolean accept(File file, String name) {
                            return name.equals(worldSettings);
                        }
                    });
                    if (settings != null)
                        return true;
                    return false;
                } else
                    return false;
            }
        });

        if (directories == null)
            return Lists.newArrayList();
        else
            return Lists.newArrayList(directories);
    }

    // Clear the world players list
    public static void clearWorldPlayers() {
        if (worldPlayers != null)
            worldPlayers.clear();
    }

    // Check if world save exist
    public static boolean exist(JavaPlugin plugin, String savedWorld) {
        return listWorlds(plugin).contains(savedWorld);
    }

    // Save a world
    public static boolean saveWorld(JavaPlugin plugin, World world, String saveAs) {
        if (world == null) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to save the world '" + world.getName() + "'. This world doesn't exist");
            return false;
        }

        // First we need to save the world to disk
        saveWorld(world);

        // Create the worldSaves folder
        new File(plugin.getDataFolder() + "/" + worldSaves + "/").mkdirs();

        // World folder
        final File worldFolder = new File(plugin.getServer().getWorldContainer(), world.getName());

        // Save as folder
        final File saveAsFolder = new File(plugin.getDataFolder() + "/" + worldSaves + "/" + saveAs);

        // Get the WorldConfig file for the saved world
        WorldConfig worldConfig = getWorldConfig(plugin, saveAs);

        // Check if the save already exists
        if (saveAsFolder.exists())
            deleteWorldFolder(saveAsFolder);
        if (saveAsFolder.exists()) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the existing world '" + saveAs + "'");
            return false;
        }

        // Copy the world
        if (!copyWorldFolder(worldFolder, saveAsFolder) || !saveAsFolder.exists()) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to copy world '" + saveAs + "'");
            return false;
        }

        // Create the WorldConfig file for the saved world
        if (worldConfig == null)
            worldConfig = getWorldConfig(plugin, saveAs);

        // Create a copy of the WorldCreator used for the world to copy
        final WorldCreator worldCreator = getWorldCreator(world);

        // Update the world config file for the saved world
        worldConfig.name = worldCreator.name();
        worldConfig.seed = worldCreator.seed();
        worldConfig.environment = worldCreator.environment().toString();
        worldConfig.generator = worldCreator.generator() != null ? worldCreator.generator().toString() : "";
        worldConfig.type = worldCreator.type().toString();
        worldConfig.generateStructures = worldCreator.generateStructures();
        worldConfig.generatorSettings = worldCreator.generatorSettings();
        worldConfig.save();

        return true;
    }

    public static boolean saveWorld(JavaPlugin plugin, String world) {
        return saveWorld(plugin, Bukkit.getServer().getWorld(world), world);
    }

    public static boolean saveWorld(JavaPlugin plugin, String world, String saveAs) {
        return saveWorld(plugin, Bukkit.getServer().getWorld(world), saveAs);
    }

    public static boolean deleteWorldSave(JavaPlugin plugin, String worldName) {
        // Folder to delete
        File worldFolder = new File(plugin.getDataFolder() + "/" + worldSaves + "/" + worldName);

        // Check
        if (!worldFolder.exists()) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the saved world '" + worldName + "'. This world doesn't exist");
            return false;
        }

        // Delete the folder
        if (worldFolder.exists() && !deleteWorldFolder(worldFolder)) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the folder '" + worldFolder.toString() + "'.");
            return false;
        }

        // Check
        if (worldFolder.exists()) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the saved world '" + worldName + "'.");
            return false;
        }

        SimplePrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                "The saved world " + worldName + " was deleted.");

        return true;
    }

    public static boolean loadWorld(JavaPlugin plugin, String savedWorld, String loadAs) {
        // The main world 'world' can't be resetted
        if (loadAs.equals("world")) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the world 'world'. The main world 'world' can't be resetted");
            return false;
        }

        // Check that the saved folder exist
        final File savedWorldFolder = new File(plugin.getDataFolder() + "/" + worldSaves + "/" + savedWorld);
        if (savedWorldFolder.exists() == false) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to load the world '" + savedWorld + "'. This world 'world' doesn't exist");
            return false;
        }

        // Load as folder
        final File loadAsFolder = new File(WorldRestorer.instance.getServer().getWorldContainer(), loadAs);

        // Get the config file for that world
        final WorldConfig worldConfig = getWorldConfig(plugin, savedWorld);
        if (worldConfig == null) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to load the config file for the world '" + savedWorld + "'.");
            return false;
        }

        // by default, remove all the players in the world
        removePlayersFromWorld(loadAs);

        // Unload the world if it exist
        if (WorldRestorer.instance.getServer().getWorld(loadAs) != null) {
            // First with Bukkit, be sure to save the world to unload all chunks
            if (WorldRestorer.instance.getServer().unloadWorld(loadAs, true) == false) {
                WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                        "Bukkit refused to unload the world '" + loadAs + "'");
                return false;
            }

            // Next with multiverse if it is present
            if (WorldRestorer.multiverse != null
                    && WorldRestorer.multiverse.getCore().getMVWorldManager().unloadWorld(loadAs, true) == false) {
                WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                        "Failed to unload the world '" + loadAs + "' using Multiverse.");
                return false;
            }

            SimplePrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "The world '" + loadAs + "' was unloaded.");
        }

        // Delete the folder containing the world
        if (loadAsFolder.exists() && !deleteWorldFolder(loadAsFolder)) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the folder '" + loadAsFolder.toString() + "'.");
            return false;
        }
        // Check that all files are deleted
        if (loadAsFolder.exists()) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete the world '" + loadAs + "'");
            return false;
        } else
            SimplePrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "The world '" + loadAs + "' was deleted.");

        // Copy the saved world
        copyWorldFolder(savedWorldFolder, loadAsFolder);
        // Check that files are copied
        if (!loadAsFolder.exists()) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to copy the world '" + savedWorld + "' to '" + loadAs + "'.");
            return false;
        } else
            SimplePrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "The world '" + savedWorld + "' has been copied to '" + loadAs + "'.");

        //load the world
        WorldCreator worldCreator = worldConfig.getWorldCreator(loadAs);
        if (WorldRestorer.multiverse != null) {
            if (WorldRestorer.multiverse.getCore().getMVWorldManager().addWorld(loadAs, worldCreator.environment(),
                    Long.toString(worldCreator.seed()), worldCreator.type(), worldCreator.generateStructures(),
                    worldCreator.generatorSettings()) == false) {
                WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                        "Failed to add the world '" + loadAs + "' using Multiverse.");
                return false;
            }
            if (WorldRestorer.multiverse.getCore().getMVWorldManager().loadWorld(loadAs) == false) {
                WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                        "Failed to load the world '" + loadAs + "' using Multiverse.");
                return false;
            }

            SimplePrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "The world '" + loadAs + "' has bee loaded using Multiverse.");
        } else {
            WorldRestorer.instance.getServer().createWorld(worldCreator);
            if (WorldRestorer.instance.getServer().getWorld(loadAs) == null) {
                WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                        "Failed to add the world '" + loadAs + "' using Bukkit.");
                return false;
            }

            SimplePrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "The world '" + loadAs + "' has bee loaded using Bukkit.");
        }

        // Events
        WorldRestorer.instance.getServer().getPluginManager()
                .callEvent(new WorldInitEvent(WorldRestorer.instance.getServer().getWorld(loadAs)));
        WorldRestorer.instance.getServer().getPluginManager()
                .callEvent(new WorldLoadEvent(WorldRestorer.instance.getServer().getWorld(loadAs)));

        return true;
    }

    public static boolean loadWorld(JavaPlugin plugin, String world) {
        return loadWorld(plugin, world, world);
    }

    private static WorldCreator getWorldCreator(World world) {
        final WorldCreator worldCreator = new WorldCreator(world.getName());
        worldCreator.copy(world);
        return worldCreator;
    }

    private static boolean saveWorld(World world) {
        // Try to save all chunks
        final Chunk[] chunks = world.getLoadedChunks();
        for (final Chunk chunk : chunks)
            NmsWorldUtil.saveChunk(world, chunk);

        // Time reference
        long reference = new Date().getTime();

        // Save the world
        world.save();

        // Wait for world to save
        try {
            long delay = 100, count = 0;
            while (count < 100) {
                long lastModify = new File(world.getWorldFolder(), "level.dat").lastModified();

                // Wait for the file to close
                if (lastModify - reference > 0) {
                    Thread.sleep(800);
                    return true;
                }

                // Wait again
                Thread.sleep(delay);

                // D'ont wait to much
                count++;
            }
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }

        System.runFinalization();
        System.gc();

        return false;
    }

    private static boolean copyWorldFolder(File sourceFolder, File destinationFolder) {
        try {
            FileUtils.copyDirectory(sourceFolder, destinationFolder);
        } catch (IOException e) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to copy folder " + sourceFolder.getName() + " to " + destinationFolder.getName());
            return false;
        }

        // Remove the uid.dat file if exist
        File uidFile = new File(destinationFolder, "uid.dat");
        if (uidFile.exists() && !FileUtils.deleteQuietly(uidFile)) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete uid.dat file from world " + destinationFolder.getName());
            return false;
        }
        // Remove the session.lock file if exist
        File sessionFile = new File(destinationFolder, "session.lock");
        if (sessionFile.exists() && !FileUtils.deleteQuietly(sessionFile)) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete session.lock file from world " + destinationFolder.getName());
            return false;
        }
        // Remove the worldSettings file if exist
        File worldSettingsFile = new File(destinationFolder, worldSettings);
        if (worldSettingsFile.exists() && !FileUtils.deleteQuietly(worldSettingsFile)) {
            WarningPrefixedMessage.toConsole(WorldRestorer.instance, prefix,
                    "Failed to delete " + worldSettings + " file from world " + destinationFolder.getName() + ".");
            return false;
        }

        return true;
    }

    private static boolean deleteWorldFolder(File dir) {
        try {
            FileUtils.deleteDirectory(dir);
            return true;
        } catch (IOException ignored) {
            return false;
        }
    }

    private static boolean isCompletelyWritten(File file) {
        RandomAccessFile stream = null;
        try {
            stream = new RandomAccessFile(file, "rw");
        } catch (Exception e) {
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                }
                return true;
            }
        }
        return false;
    }

    public static WorldConfig getWorldConfig(JavaPlugin plugin, String savedWorldName) {
        // The world folder
        final File savedWorldFolder = new File(plugin.getDataFolder() + "/" + worldSaves + "/" + savedWorldName);
        if (savedWorldFolder.exists() == false)
            return null;

        //
        final WorldConfig worldConfig = new WorldConfig(WorldRestorer.instance, savedWorldFolder, worldSettings,
                true);
        if (worldConfig.load() == false)
            return null;

        return worldConfig;
    }

    private static void kickPlayersFromWorld(World world, String kickMessage) {
        if (world == null)
            return;

        List<Player> ps = world.getPlayers();
        for (Player p : ps) {
            p.saveData();
            p.kickPlayer(kickMessage);
        }
    }

    public static void kickPlayersFromWorld(String worldName, String kickMessage) {
        World world = Bukkit.getWorld(worldName);
        kickPlayersFromWorld(world, kickMessage);
    }

    public static void removePlayersFromWorld(World world) {
        if (world == null)
            return;
        if (world.getPlayers().size() == 0)
            return;

        // Keep trace of all players in the world
        worldPlayers = world.getPlayers();

        // Remove the players
        if (WorldRestorer.multiverse != null) {
            WorldRestorer.multiverse.getCore().getMVWorldManager().removePlayersFromWorld(world.getName());
        } else {
            World safeWorld = WorldRestorer.instance.getServer().getWorlds().get(0);
            for (Player p : worldPlayers) {
                p.teleport(safeWorld.getSpawnLocation());
            }
        }
    }

    public static void removePlayersFromWorld(String worldName) {
        World world = Bukkit.getWorld(worldName);
        removePlayersFromWorld(world);
    }

    public static void respawnPlayersInWorld(World world) {
        if (world == null)
            return;
        if (worldPlayers == null)
            return;
        if (worldPlayers.size() == 0)
            return;

        // Respawn the players
        if (WorldRestorer.multiverse != null) {
            SafeTTeleporter teleporter = WorldRestorer.multiverse.getCore().getSafeTTeleporter();
            for (Player p : worldPlayers) {
                if (p.isOnline())
                    teleporter.safelyTeleport(null, p, world.getSpawnLocation(), true);
            }
        } else {
            for (Player p : worldPlayers) {
                if (p.isOnline())
                    p.teleport(world.getSpawnLocation());
            }
        }

        // Empty the list
        worldPlayers.clear();
    }

    public static void respawnPlayersInWorld(String worldName) {
        World world = Bukkit.getWorld(worldName);
        respawnPlayersInWorld(world);
    }

    public static void spawnPlayersInWorld(World world, Location location) {
        if (world == null)
            return;
        if (worldPlayers == null)
            return;
        if (worldPlayers.size() == 0)
            return;

        Location teleportLocation = location.clone();
        teleportLocation.setWorld(world);

        // Teleport players
        for (Player p : worldPlayers) {
            p.teleport(location);
        }
    }

    public static void spawnPlayersInWorld(String worldName, Location location) {
        World world = Bukkit.getWorld(worldName);
        spawnPlayersInWorld(world, location);
    }

    public static void sendMessageInWorld(World world, String message) {
        if (world == null)
            return;

        for (Player p : world.getPlayers()) {
            p.sendMessage(message);
        }
    }

    public static void sendMessageInWorld(String worldName, String message) {
        World world = Bukkit.getWorld(worldName);
        sendMessageInWorld(world, message);
    }
}