Improve stability of instantiation system

This commit is contained in:
Daniel Saukel 2018-06-10 23:17:11 +02:00
parent 6a7f543c9e
commit ef17d01ab8
6 changed files with 86 additions and 44 deletions

View File

@ -36,7 +36,6 @@ import de.erethon.dungeonsxl.mob.DMobListener;
import de.erethon.dungeonsxl.mob.DMobType; import de.erethon.dungeonsxl.mob.DMobType;
import de.erethon.dungeonsxl.mob.ExternalMobProviderCache; import de.erethon.dungeonsxl.mob.ExternalMobProviderCache;
import de.erethon.dungeonsxl.player.DClassCache; import de.erethon.dungeonsxl.player.DClassCache;
import de.erethon.dungeonsxl.player.DGamePlayer;
import de.erethon.dungeonsxl.player.DGroup; import de.erethon.dungeonsxl.player.DGroup;
import de.erethon.dungeonsxl.player.DPermission; import de.erethon.dungeonsxl.player.DPermission;
import de.erethon.dungeonsxl.player.DPlayerCache; import de.erethon.dungeonsxl.player.DPlayerCache;
@ -139,11 +138,6 @@ public class DungeonsXL extends DREPlugin {
saveData(); saveData();
messageConfig.save(); messageConfig.save();
// DGamePlayer leaves World
for (DGamePlayer dPlayer : dPlayers.getDGamePlayers()) {
dPlayer.leave();
}
dGroups.clear(); dGroups.clear();
// Delete DWorlds // Delete DWorlds

View File

@ -20,7 +20,6 @@ import de.erethon.commons.misc.FileUtil;
import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.event.editworld.EditWorldSaveEvent; import de.erethon.dungeonsxl.event.editworld.EditWorldSaveEvent;
import de.erethon.dungeonsxl.event.editworld.EditWorldUnloadEvent; import de.erethon.dungeonsxl.event.editworld.EditWorldUnloadEvent;
import de.erethon.dungeonsxl.player.DEditPlayer;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@ -28,7 +27,6 @@ import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
/** /**
@ -157,10 +155,7 @@ public class DEditWorld extends DInstanceWorld {
return; return;
} }
for (Player player : getWorld().getPlayers()) { kickAllPlayers();
DEditPlayer dPlayer = DEditPlayer.getByPlayer(player);
dPlayer.leave();
}
if (!plugin.getMainConfig().areTweaksEnabled()) { if (!plugin.getMainConfig().areTweaksEnabled()) {
if (save) { if (save) {

View File

@ -496,6 +496,8 @@ public class DGameWorld extends DInstanceWorld {
return; return;
} }
kickAllPlayers();
if (!plugin.getMainConfig().areTweaksEnabled()) { if (!plugin.getMainConfig().areTweaksEnabled()) {
Bukkit.unloadWorld(getWorld(), false); Bukkit.unloadWorld(getWorld(), false);
FileUtil.removeDir(getFolder()); FileUtil.removeDir(getFolder());
@ -552,6 +554,9 @@ public class DGameWorld extends DInstanceWorld {
Player player = event.getPlayer(); Player player = event.getPlayer();
Block block = event.getBlock(); Block block = event.getBlock();
for (DSign dSign : dSigns) { for (DSign dSign : dSigns) {
if (dSign == null) {
continue;
}
if ((block.equals(dSign.getSign().getBlock()) || block.equals(BlockUtil.getAttachedBlock(dSign.getSign().getBlock()))) && dSign.getType().isProtected()) { if ((block.equals(dSign.getSign().getBlock()) || block.equals(BlockUtil.getAttachedBlock(dSign.getSign().getBlock()))) && dSign.getType().isProtected()) {
return true; return true;
} }

View File

@ -17,10 +17,15 @@
package de.erethon.dungeonsxl.world; package de.erethon.dungeonsxl.world;
import de.erethon.commons.chat.MessageUtil; import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.player.PlayerUtil;
import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.game.GameRuleProvider; import de.erethon.dungeonsxl.game.GameRuleProvider;
import de.erethon.dungeonsxl.player.DGamePlayer; import de.erethon.dungeonsxl.player.DGamePlayer;
import de.erethon.dungeonsxl.player.DInstancePlayer;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
@ -114,6 +119,20 @@ public abstract class DInstanceWorld {
this.lobby = lobby; this.lobby = lobby;
} }
/**
* @return
* the players in this world
*/
public Collection<DInstancePlayer> getPlayers() {
Collection<DInstancePlayer> players = new ArrayList<>();
for (DInstancePlayer player : plugin.getDPlayers().getDInstancePlayers()) {
if (player.getWorld().equals(world)) {
players.add(player);
}
}
return players;
}
/* Actions */ /* Actions */
/** /**
* Sends a message to all players in the instance. * 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 * @param rules
* sets up the time and weather to match the rules * sets up the time and weather to match the rules

View File

@ -16,6 +16,7 @@
*/ */
package de.erethon.dungeonsxl.world; package de.erethon.dungeonsxl.world;
import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.misc.FileUtil; import de.erethon.commons.misc.FileUtil;
import de.erethon.commons.worldloader.WorldLoader; import de.erethon.commons.worldloader.WorldLoader;
import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.DungeonsXL;
@ -25,6 +26,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.WorldCreator; import org.bukkit.WorldCreator;
import org.bukkit.WorldType; import org.bukkit.WorldType;
@ -209,12 +211,24 @@ public class DResourceWorld {
public DInstanceWorld instantiate(final boolean game) { public DInstanceWorld instantiate(final boolean game) {
int id = worlds.generateId(); int id = worlds.generateId();
String name = worlds.generateName(game, id); String name = worlds.generateName(game, id);
final File instanceFolder = new File(Bukkit.getWorldContainer(), name); File tempIF = new File(Bukkit.getWorldContainer(), name);
while (tempIF.exists()) {
while (Bukkit.getWorld(name) != null) { 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++; id++;
name = worlds.generateName(game, 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); 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); DEditWorld editWorld = (DEditWorld) instantiate(false);
editWorld.generateIdFile();
return editWorld; return editWorld;
} }
@ -306,6 +319,7 @@ public class DResourceWorld {
FileUtil.copyDir(DWorldCache.RAW, folder, DungeonsXL.EXCLUDED_FILES); FileUtil.copyDir(DWorldCache.RAW, folder, DungeonsXL.EXCLUDED_FILES);
editWorld.generateIdFile(); editWorld.generateIdFile();
editWorld.world = WorldLoader.createWorld(creator); editWorld.world = WorldLoader.createWorld(creator);
editWorld.generateIdFile();
} }
}.runTaskAsynchronously(plugin); }.runTaskAsynchronously(plugin);
} }

View File

@ -211,14 +211,22 @@ public class DWorldCache {
*/ */
public void check() { public void check() {
for (File file : Bukkit.getWorldContainer().listFiles()) { for (File file : Bukkit.getWorldContainer().listFiles()) {
if (file.getName().startsWith("DXL_Edit_") && file.isDirectory()) { if (!file.getName().startsWith("DXL_") || !file.isDirectory()) {
continue;
}
if (file.getName().startsWith("DXL_Edit_")) {
for (File mapFile : file.listFiles()) { for (File mapFile : file.listFiles()) {
if (mapFile.getName().startsWith(".id_")) { if (!mapFile.getName().startsWith(".id_")) {
continue;
}
String name = mapFile.getName().substring(4); String name = mapFile.getName().substring(4);
File resource = new File(DungeonsXL.MAPS, name); File resource = new File(DungeonsXL.MAPS, name);
File backup = new File(DungeonsXL.BACKUPS, resource.getName() + "-" + System.currentTimeMillis() + "_crashbackup"); File backup = new File(DungeonsXL.BACKUPS, resource.getName() + "-" + System.currentTimeMillis() + "_crashbackup");
FileUtil.copyDir(resource, backup); 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: remove:
for (File remove : FileUtil.getFilesForFolder(resource)) { for (File remove : FileUtil.getFilesForFolder(resource)) {
for (String nope : DungeonsXL.EXCLUDED_FILES) { for (String nope : DungeonsXL.EXCLUDED_FILES) {
@ -230,16 +238,12 @@ public class DWorldCache {
} }
deleteUnusedFiles(file); deleteUnusedFiles(file);
FileUtil.copyDir(file, resource, DungeonsXL.EXCLUDED_FILES); FileUtil.copyDir(file, resource, DungeonsXL.EXCLUDED_FILES);
FileUtil.removeDir(file);
} }
} }
} else if (file.getName().startsWith("DXL_Game_") && file.isDirectory()) {
FileUtil.removeDir(file); FileUtil.removeDir(file);
} }
} }
}
/** /**
* Clean up all instances. * Clean up all instances.