Resetting a world

Discussion in 'Spigot Plugin Development' started by RandomRobinnnn, May 27, 2017.

  1. Howdy spigot!

    Allow me to quicly explain how I've set up things:

    The root of the server contains one extra folder called "Game Worlds"
    In the onEnable of my plugin all the worlds get loaded with load()
    When a world needs to be reset, I use rebuild(world)

    This is the regarding code:

    Code (Text):

         public static void rebuild(World world) {
            String worldName = world.getName();
            delete(world);
            new BukkitRunnable() {
               
                @Override
                public void run() {
                    load(worldName);
                }
            }.runTaskLater(Main.getPlugin(), 60L);
        }

        private static void load(String worldName) {
            Console.log("Loading world " + worldName + "...");
            File rootDir = new File("").getAbsoluteFile();
            File unloadedWorldsDir = new File(rootDir, "Game Worlds");
            File from = new File(unloadedWorldsDir, worldName);
            File to = new File(rootDir, worldName);
            try {
                to.mkdir();

                FileUtils.copyDirectory(from, to);

                Bukkit.createWorld(new WorldCreator(worldName));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

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

        private static void delete(World world) {
            File path = world.getWorldFolder();
            // Bukkit.getWorlds().remove(world);
            unload(world);
            deletePath(path);
        }

        private static void unload(World world) {
    //        String Name = world.getName();
            if (!world.equals(null)) {
                for (Player p : world.getPlayers()) {
                    p.teleport(Bukkit.getWorlds().get(0).getSpawnLocation());
                }
                Bukkit.getServer().unloadWorld(world, true);
            }
        }
    I've tried many different solutions. Some of which might be commented out. Here's what happens:

    Plugin loads
    Game worlds are being copied from folder "Game Worlds" to the root of the server (each in its own folder)
    Game worlds are being loaded
    Game world are all how they should be
    Game ends and rebuild(world) is called
    Regarding world gets unloaded
    Regarding world folder gets removed (The one in the root)
    Regarding world gets copied from folder "Game World" to the root of the server
    Regarding world gets loaded

    Now this is where things start to get strange. In the folder "Game Worlds" are 3 diffrent worlds. 2 of which are void worlds with one arena per world. The other one is a regular world. When teleporting to regular world, everything *seems* fine. However, when I teleport to one of the void worlds, it's complete void. (Yes, I checked the co-ordinates, but no arena's popped up).

    Hmm. Yeah, that doesn't make much sense. Especially since loading the world the second time uses exacly the same method as the first time. But wait, there's more! When I've teleported to one of the void worlds, and I made sure it was 'broken', I took the contents of the world folder, and placed that inside a single-player world. And there it was! The world looked just fine in single-player!

    Now, that was my problem explained. What I think might have happend is the following:

    When I unload the world, and I remove it from the disk, It's still in the memory of the server. Just not accessable. When I then load the world again, it takes the part it remembers and just loads that.

    Another thing that made me conclude the above is that I've deleted the world without replacing it again. Not sure what I did to load it again, but I could enter that world again. But the world wasn't even in the server root...

    And there it is, my problem to which I would love a solution for. If you have any idea whatsoever on how to achieve what I want, or what is actually happening, I'd love to hear it!

    Thank you for your time (I know, it was a lot),

    - RandomRobinnnn
     
  2. When you're unloading a world inside of your #unload() method, do Bukkit.getServer().unloadWorld(world, false); False makes it that it does not save the world that you're unloading.
     
  3. Doing that will give me problems while removing the region folder inside the world folder. It also throws some errors in the console like this one

     
  4. I do believe I finally found the solution to my problem. After I unload my world I use world = null. I believe the world is still loaded with this variable, so putting it to null destroys the memory of this world. Loading it again fixed this issue.