diff --git a/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java b/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java index a841fded..f3c96c5e 100644 --- a/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java +++ b/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java @@ -36,7 +36,6 @@ import de.erethon.dungeonsxl.mob.DMobListener; import de.erethon.dungeonsxl.mob.DMobType; import de.erethon.dungeonsxl.mob.ExternalMobProviderCache; import de.erethon.dungeonsxl.player.DClassCache; -import de.erethon.dungeonsxl.player.DGamePlayer; import de.erethon.dungeonsxl.player.DGroup; import de.erethon.dungeonsxl.player.DPermission; import de.erethon.dungeonsxl.player.DPlayerCache; @@ -139,11 +138,6 @@ public class DungeonsXL extends DREPlugin { saveData(); messageConfig.save(); - // DGamePlayer leaves World - for (DGamePlayer dPlayer : dPlayers.getDGamePlayers()) { - dPlayer.leave(); - } - dGroups.clear(); // Delete DWorlds diff --git a/src/main/java/de/erethon/dungeonsxl/world/DEditWorld.java b/src/main/java/de/erethon/dungeonsxl/world/DEditWorld.java index 8954c28f..d2eb3508 100644 --- a/src/main/java/de/erethon/dungeonsxl/world/DEditWorld.java +++ b/src/main/java/de/erethon/dungeonsxl/world/DEditWorld.java @@ -20,7 +20,6 @@ import de.erethon.commons.misc.FileUtil; import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.event.editworld.EditWorldSaveEvent; import de.erethon.dungeonsxl.event.editworld.EditWorldUnloadEvent; -import de.erethon.dungeonsxl.player.DEditPlayer; import java.io.File; import java.io.IOException; import java.util.concurrent.CopyOnWriteArrayList; @@ -28,7 +27,6 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.Sign; -import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; /** @@ -157,10 +155,7 @@ public class DEditWorld extends DInstanceWorld { return; } - for (Player player : getWorld().getPlayers()) { - DEditPlayer dPlayer = DEditPlayer.getByPlayer(player); - dPlayer.leave(); - } + kickAllPlayers(); if (!plugin.getMainConfig().areTweaksEnabled()) { if (save) { diff --git a/src/main/java/de/erethon/dungeonsxl/world/DGameWorld.java b/src/main/java/de/erethon/dungeonsxl/world/DGameWorld.java index ff6d455c..d5d4b0c1 100644 --- a/src/main/java/de/erethon/dungeonsxl/world/DGameWorld.java +++ b/src/main/java/de/erethon/dungeonsxl/world/DGameWorld.java @@ -496,6 +496,8 @@ public class DGameWorld extends DInstanceWorld { return; } + kickAllPlayers(); + if (!plugin.getMainConfig().areTweaksEnabled()) { Bukkit.unloadWorld(getWorld(), false); FileUtil.removeDir(getFolder()); @@ -552,6 +554,9 @@ public class DGameWorld extends DInstanceWorld { Player player = event.getPlayer(); Block block = event.getBlock(); for (DSign dSign : dSigns) { + if (dSign == null) { + continue; + } if ((block.equals(dSign.getSign().getBlock()) || block.equals(BlockUtil.getAttachedBlock(dSign.getSign().getBlock()))) && dSign.getType().isProtected()) { return true; } diff --git a/src/main/java/de/erethon/dungeonsxl/world/DInstanceWorld.java b/src/main/java/de/erethon/dungeonsxl/world/DInstanceWorld.java index 2fec3218..1b296d9e 100644 --- a/src/main/java/de/erethon/dungeonsxl/world/DInstanceWorld.java +++ b/src/main/java/de/erethon/dungeonsxl/world/DInstanceWorld.java @@ -17,10 +17,15 @@ package de.erethon.dungeonsxl.world; import de.erethon.commons.chat.MessageUtil; +import de.erethon.commons.player.PlayerUtil; import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.game.GameRuleProvider; import de.erethon.dungeonsxl.player.DGamePlayer; +import de.erethon.dungeonsxl.player.DInstancePlayer; import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -114,6 +119,20 @@ public abstract class DInstanceWorld { this.lobby = lobby; } + /** + * @return + * the players in this world + */ + public Collection getPlayers() { + Collection players = new ArrayList<>(); + for (DInstancePlayer player : plugin.getDPlayers().getDInstancePlayers()) { + if (player.getWorld().equals(world)) { + players.add(player); + } + } + return players; + } + /* Actions */ /** * Sends a message to all players in the instance. @@ -127,6 +146,17 @@ public abstract class DInstanceWorld { } } + /** + * Makes all players leave the world. + * Attempts to let them leave properly if they are correct DInstancePlayers; + * teleports them to the spawn if they are not. + */ + public void kickAllPlayers() { + getPlayers().forEach(p -> p.leave()); + // Players who shouldn't be in the dungeon but still are for some reason + world.getPlayers().forEach(p -> PlayerUtil.secureTeleport(p, Bukkit.getWorlds().get(0).getSpawnLocation())); + } + /** * @param rules * sets up the time and weather to match the rules diff --git a/src/main/java/de/erethon/dungeonsxl/world/DResourceWorld.java b/src/main/java/de/erethon/dungeonsxl/world/DResourceWorld.java index 4041381f..e0851678 100644 --- a/src/main/java/de/erethon/dungeonsxl/world/DResourceWorld.java +++ b/src/main/java/de/erethon/dungeonsxl/world/DResourceWorld.java @@ -16,6 +16,7 @@ */ package de.erethon.dungeonsxl.world; +import de.erethon.commons.chat.MessageUtil; import de.erethon.commons.misc.FileUtil; import de.erethon.commons.worldloader.WorldLoader; import de.erethon.dungeonsxl.DungeonsXL; @@ -25,6 +26,7 @@ import java.io.File; import java.io.IOException; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.WorldCreator; import org.bukkit.WorldType; @@ -209,12 +211,24 @@ public class DResourceWorld { public DInstanceWorld instantiate(final boolean game) { int id = worlds.generateId(); String name = worlds.generateName(game, id); - final File instanceFolder = new File(Bukkit.getWorldContainer(), name); - - while (Bukkit.getWorld(name) != null) { - id++; - name = worlds.generateName(game, id); + File tempIF = new File(Bukkit.getWorldContainer(), name); + while (tempIF.exists()) { + World world = Bukkit.getWorld(name); + boolean removed = false; + if (world != null && world.getPlayers().isEmpty()) { + Bukkit.unloadWorld(name, false); + } + if (world == null || world.getPlayers().isEmpty()) { + removed = tempIF.delete(); + } + if (!removed) { + MessageUtil.log(plugin, "&6Warning: An unrecognized junk instance (&4" + name + "&6) has been found, but could not be deleted."); + id++; + name = worlds.generateName(game, id); + tempIF = new File(Bukkit.getWorldContainer(), name); + } } + final File instanceFolder = tempIF; // Because Java SUCKS final DInstanceWorld instance = game ? new DGameWorld(this, instanceFolder, id) : new DEditWorld(this, instanceFolder, id); @@ -263,7 +277,6 @@ public class DResourceWorld { } DEditWorld editWorld = (DEditWorld) instantiate(false); - editWorld.generateIdFile(); return editWorld; } @@ -306,6 +319,7 @@ public class DResourceWorld { FileUtil.copyDir(DWorldCache.RAW, folder, DungeonsXL.EXCLUDED_FILES); editWorld.generateIdFile(); editWorld.world = WorldLoader.createWorld(creator); + editWorld.generateIdFile(); } }.runTaskAsynchronously(plugin); } diff --git a/src/main/java/de/erethon/dungeonsxl/world/DWorldCache.java b/src/main/java/de/erethon/dungeonsxl/world/DWorldCache.java index dead28de..5284fb4d 100644 --- a/src/main/java/de/erethon/dungeonsxl/world/DWorldCache.java +++ b/src/main/java/de/erethon/dungeonsxl/world/DWorldCache.java @@ -211,33 +211,37 @@ public class DWorldCache { */ public void check() { for (File file : Bukkit.getWorldContainer().listFiles()) { - if (file.getName().startsWith("DXL_Edit_") && file.isDirectory()) { - for (File mapFile : file.listFiles()) { - if (mapFile.getName().startsWith(".id_")) { - String name = mapFile.getName().substring(4); - - File resource = new File(DungeonsXL.MAPS, name); - File backup = new File(DungeonsXL.BACKUPS, resource.getName() + "-" + System.currentTimeMillis() + "_crashbackup"); - FileUtil.copyDir(resource, backup); - remove: - for (File remove : FileUtil.getFilesForFolder(resource)) { - for (String nope : DungeonsXL.EXCLUDED_FILES) { - if (remove.getName().equals(nope)) { - continue remove; - } - } - remove.delete(); - } - deleteUnusedFiles(file); - FileUtil.copyDir(file, resource, DungeonsXL.EXCLUDED_FILES); - - FileUtil.removeDir(file); - } - } - - } else if (file.getName().startsWith("DXL_Game_") && file.isDirectory()) { - FileUtil.removeDir(file); + if (!file.getName().startsWith("DXL_") || !file.isDirectory()) { + continue; } + + if (file.getName().startsWith("DXL_Edit_")) { + for (File mapFile : file.listFiles()) { + if (!mapFile.getName().startsWith(".id_")) { + continue; + } + + String name = mapFile.getName().substring(4); + + File resource = new File(DungeonsXL.MAPS, name); + File backup = new File(DungeonsXL.BACKUPS, resource.getName() + "-" + System.currentTimeMillis() + "_crashbackup"); + FileUtil.copyDir(resource, backup); + // Remove all files from the backupped resource world but not the config & data that we cannot fetch from the instance. + remove: + for (File remove : FileUtil.getFilesForFolder(resource)) { + for (String nope : DungeonsXL.EXCLUDED_FILES) { + if (remove.getName().equals(nope)) { + continue remove; + } + } + remove.delete(); + } + deleteUnusedFiles(file); + FileUtil.copyDir(file, resource, DungeonsXL.EXCLUDED_FILES); + } + } + + FileUtil.removeDir(file); } }