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.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

View File

@ -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) {

View File

@ -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;
}

View File

@ -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<DInstancePlayer> getPlayers() {
Collection<DInstancePlayer> 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

View File

@ -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) {
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);
}

View File

@ -211,14 +211,22 @@ public class DWorldCache {
*/
public void check() {
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()) {
if (mapFile.getName().startsWith(".id_")) {
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) {
@ -230,16 +238,12 @@ public class DWorldCache {
}
deleteUnusedFiles(file);
FileUtil.copyDir(file, resource, DungeonsXL.EXCLUDED_FILES);
FileUtil.removeDir(file);
}
}
} else if (file.getName().startsWith("DXL_Game_") && file.isDirectory()) {
FileUtil.removeDir(file);
}
}
}
/**
* Clean up all instances.