Hello! I'm trying to solve a problem in connection with Bukkit's world loading. I saw a topic on the Bukkit Forums about that, but i still can't unload my world. I'm struggling on that problem for 3 days and i can't figure it out so i would like to request your help. We are creating a minecraft PVP server, where players can join pvp matches(battlegrounds, arenas) and these matches can go independently from other matches. Here is the class for a PVP Match: Code: package hu.battlecraft.PVP; import hu.battlecraft.BattleCraft; import hu.battlecraft.Misc.Helper; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.entity.Player; public class PVPMatch { public int ID; public MapTemplate template; public Integer ElapsedSeconds; public boolean Started = false; public String world_name; public Player[] Players; public PVPMatch(String world_name, MapTemplate template, Player[] players){ this.template = template; this.Players = players; this.Started = false; this.world_name = world_name; if(Bukkit.getWorld(world_name) == null){ Close(); } for(Player p : players){ p.teleport(Bukkit.getWorld(world_name).getSpawnLocation()); } } public void Close(){ if(Bukkit.getWorld(world_name) != null){ for (Player player : Bukkit.getWorld(world_name).getPlayers()) { player.teleport(Bukkit.getServer().getWorld("lobby").getSpawnLocation()); player.sendMessage("A világ amiben voltál többé nem létezik!"); } if(Bukkit.getWorld(world_name).getLoadedChunks() != null && Bukkit.getWorld(world_name).getLoadedChunks().length > 0){ for(Chunk c : Bukkit.getWorld(world_name).getLoadedChunks()){ c.unload(false, true); } } BattleCraft.access.forceUnloadWorld(Bukkit.getWorld(world_name)); BattleCraft.access.clearWorldReference(world_name); Bukkit.getServer().getScheduler().runTaskLaterAsynchronously(BattleCraft.inst, new WorldDeleter(world_name), 80); } } private class WorldDeleter implements Runnable { String[] worlds; static final long retryDelay = 30; static final int maxRetries = 5; int attempt; public WorldDeleter(String name) { attempt = 0; worlds = new String[1]; worlds[0] = name; } public void run() { boolean allGood = true; for ( String world : worlds ) allGood = allGood && Helper.deleteWorld(world); if ( !allGood ) if ( attempt < maxRetries ) { BattleCraft.logger.info("Retrying world data deletion..."); attempt++; Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(BattleCraft.inst, this, retryDelay); return; } else BattleCraft.logger.warning("Failed to delete some world information!"); } } } Note: BattleCraft.access is an instance of CraftBukkitAccess class from the plugin "Killer". I think i didn't create any reference to my worlds, but when i try to unload it it says "Failed to delete some world information!" so it still holds a reference somewhere, but i don't know where or what can i do. Thanks in advance. S0undX Anyone? EDIT by Moderator: merged posts, please use the edit button instead of double posting.
s0undx Your plugin or another one is probably holding a reference to the World preventing you from deleting it. I suggest you remove plugins one by one until you find the culprit.
What is a World reference EXACTLY? Any world class intance is a reference? PS: (I already removed all the plugins except my plugin and i can't unload the world.)
s0undx Then maybe your plugin is holding a reference to the world preventing you from unloading it. To give you an idea of scope. Player ---> References Location ---> References Chunk ----> References World The main problem I'd guess is your Player[] array. Never store a player variable, only the players name as a String and then get the Player object when you need it.
Ok, thats right, but if you look on the code, you can see this part: Code: public void Close(){ if(Bukkit.getWorld(world_name) != null){ for (Player player : Bukkit.getWorld(world_name).getPlayers()) { player.teleport(Bukkit.getServer().getWorld("lobby").getSpawnLocation()); player.sendMessage("A világ amiben voltál többé nem létezik!"); } if(Bukkit.getWorld(world_name).getLoadedChunks() != null && Bukkit.getWorld(world_name).getLoadedChunks().length > 0){ for(Chunk c : Bukkit.getWorld(world_name).getLoadedChunks()){ c.unload(false, true); } } Which means that even if i hold a Player[] that reference will be pointing to my main world called "lobby". Even after updating my code, i can't unload the world, with the same error. Here is the new code of the updated class
s0undx Ok but you don't know how it is updated behind the scenes. As a matter of principal you should never store a Player object unless you can be 100% sure it will be discarded. Just change your array of players to a String[] array. And then loop through it as you have done and just include. Player p = Bukkit.getServer().getPlayer(playerName); And try unloading your world that way, then if you have problems we know the cause is something else.
s0undx Sorry I must have skipped over that last part. Sorry I can't see anything else that would cause a problem. Maybe if you try calling Bukkit.unloadWorld(name, save)?
Adamki11s Code: access.forceUnloadWorld(Bukkit.getWorld(world_name)); does that for me if i am right. http://pastebin.com/raw.php?i=jRX1EqBD
Adamki11s It does not invoke that method, but it does tha same thing, except its better according to FTWinston.
Adamki11s I already tried the default way, it wasn't working, so i was searching for like 2 days when i found this way, none of them works, i am so sad.
Adamki11s Yes, the only one i found was "Killer", and part of my code is copied from that plugin, but it still doesn't work. If you know any other plugins please tell me.
The problem was with 2 functions: 1.forceUnloadWorld did not work properly for me. Finally here is my new code to unload a world: http://pastebin.com/raw.php?i=0CJWjU51 2. clearReference could not handle properly a World which is not in the main folder. I am not an expert in IO functions, so i couldn't make a proper solution, but a hacky one: http://pastebin.com/raw.php?i=QEaxQqST Nevermind the debug messages, they were for me. (Solved, with the attached code you can delete the world.) Adamki11s
s0undx The only thing I can think of now is maybe to force Java GC after you cleared all the world references and hope that it wipes them and maybe then you will be able to delete your world? Code:java System.gc();
Adamki11s My last post was trying to say its solved. With the code i attached i am able to delete my world from a simple IO function.