How to copy and save worlds?

Discussion in 'Spigot Plugin Development' started by MSWS, Jun 1, 2018.

  1. Im working on a mini games type of plugin, and in this game players are allowed to place/ break certain blocks. I’ve thought of a few approaches for rolling back the map, but I can’t figure out how to access the world file, save it, and reload it on demand.

    Please help, and thanks!

    (I don’t want to use the shady way of setting the auto save to false.)
     
  2. You can use FAWE Api and copy paste and delete the map
     
  3. Is your server hosted on a VPS / Dedicated with like a Linux or Windows OS? Or is it from a Minecraft hosting company?
     
  4. Here's the methods class I use to delete or copy worlds:
    Code (Text):
    public class Restore {
        private World world;
        public static void copyCode(File source, File target){
            try {
                ArrayList<String> ignore = new ArrayList<String>(Arrays.asList("uid.dat", "session.dat"));
                if(!ignore.contains(source.getName())) {
                    if(source.isDirectory()) {
                        if(!target.exists())
                            target.mkdirs();
                        String files[] = source.list();
                        assert files != null;
                        for (String file : files) {
                            File srcFile = new File(source, file);
                            File destFile = new File(target, file);
                            copyCode(srcFile, destFile);
                        }
                    } else {
                        InputStream in = new FileInputStream(source);
                        OutputStream out = new FileOutputStream(target);
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = in.read(buffer)) > 0)
                            out.write(buffer, 0, length);
                        in.close();
                        out.close();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        public static boolean deleteWorldCode(File path) {
            if(path.exists()) {
                File files[] = path.listFiles();
                for(int i=0; i<files.length; i++) {
                    if(files[i].isDirectory()) {
                        deleteWorldCode(files[i]);
                    } else {
                        files[i].delete();
                    }
                }
            }
            return(path.delete());
        }

        public static void deleteUserWorld(Player p) {
            World target = p.getWorld();

            try {
                Bukkit.getServer().unloadWorld(target, true);
            }catch(Exception e) {
                System.out.println("Error restoring the world");
                return;
            }
            File worldFolder = target.getWorldFolder();
            deleteWorldCode(worldFolder);
        }
    }
     
    You cannot delete the Main world and remember to unload the world before trying to delete it
     
  5. MiniDigger

    Supporter

    why is setting auto save to false the shady way? why would you need to save worlds for minigames?
    on start, just load the map, let players play, unload and delete the map folder. for the next game, just load the map again
     
  6. It just seemed like a dodgy way of doing it. I resulted doing it your way so I suppose it’s good. Is there a way for a plugin to set Bukkit’s auto save rate of worlds to -1? Or does the server owner have to do it manually?
     
  7. MiniDigger

    Supporter

    you can set autosave to false for the world, however if you use paper their incremental auto save will override that iirc
    doesn't matter that much anyways, since you will be throwing away worlds and copying your template world, thats way more secure.
     
  8. I think the Bukkit auto save saves in the middle of games sometimes. The error went away when I manually set (via bukkit.yml) the auto save rate to -1. Just setting the worlds auto save to false didn’t work.
     
  9. A small side note: Instead of deleting and resetting the whole world it's also possible to log the modifications made by players and only reroll those.
    Just overwritting the map with a new file everytime might be easier though.
     
  10. MiniDigger

    Supporter

    make sure to delete the session lock before loading the world, then you shouldn't get any errors.
    That's really not worth the pain. You trade a bit of disk io vs CPU time at runtime and higher mem usage, plus increased complexity of your code.
     
  11. I’ve done this before and it works half decently. I like this way better though.

    How do I delete the session lock? Sorry if that’s a noob question.
     
  12. MiniDigger

    Supporter

    Just delete the file ^^