Add a delay between unloading and saving edit worlds (WIP)

This commit is contained in:
Daniel Saukel 2020-04-19 00:21:43 +02:00
parent e7f1c3cf6e
commit 95c7220f4a
6 changed files with 88 additions and 8 deletions

View File

@ -80,6 +80,7 @@ import de.erethon.dungeonsxl.trigger.TriggerListener;
import de.erethon.dungeonsxl.trigger.TriggerTypeCache; import de.erethon.dungeonsxl.trigger.TriggerTypeCache;
import de.erethon.dungeonsxl.util.LWCUtil; import de.erethon.dungeonsxl.util.LWCUtil;
import de.erethon.dungeonsxl.util.PlaceholderUtil; import de.erethon.dungeonsxl.util.PlaceholderUtil;
import de.erethon.dungeonsxl.world.DEditWorld;
import de.erethon.dungeonsxl.world.DResourceWorld; import de.erethon.dungeonsxl.world.DResourceWorld;
import de.erethon.dungeonsxl.world.DWorldListener; import de.erethon.dungeonsxl.world.DWorldListener;
import de.erethon.dungeonsxl.world.LWCIntegration; import de.erethon.dungeonsxl.world.LWCIntegration;
@ -436,7 +437,7 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI {
public void saveData() { public void saveData() {
protections.saveAll(); protections.saveAll();
instanceCache.getAllIf(i -> i instanceof EditWorld).forEach(i -> ((EditWorld) i).save()); instanceCache.getAllIf(i -> i instanceof EditWorld).forEach(i -> ((DEditWorld) i).forceSave());
} }
public void loadData() { public void loadData() {

View File

@ -48,7 +48,7 @@ public class MainConfig extends DREConfig {
NEVER NEVER
} }
public static final int CONFIG_VERSION = 17; public static final int CONFIG_VERSION = 18;
private String language = "english"; private String language = "english";
private boolean enableEconomy = false; private boolean enableEconomy = false;
@ -96,6 +96,7 @@ public class MainConfig extends DREConfig {
/* Performance */ /* Performance */
private int maxInstances = 10; private int maxInstances = 10;
private int editInstanceRemovalDelay = 5;
/* Secure Mode */ /* Secure Mode */
private boolean secureModeEnabled = false; private boolean secureModeEnabled = false;
@ -385,6 +386,20 @@ public class MainConfig extends DREConfig {
this.maxInstances = maxInstances; this.maxInstances = maxInstances;
} }
/**
* @return the delay in seconds until an edit world without players is saved and removed
*/
public int getEditInstanceRemovalDelay() {
return editInstanceRemovalDelay;
}
/**
* @param delay the delay in seconds until an edit world without players is saved and removed
*/
public void setEditInstanceRemovalDelay(int delay) {
editInstanceRemovalDelay = delay;
}
/** /**
* @return if the secure mode is enabled * @return if the secure mode is enabled
*/ */
@ -559,6 +574,10 @@ public class MainConfig extends DREConfig {
config.set("maxInstances", maxInstances); config.set("maxInstances", maxInstances);
} }
if (!config.contains("editInstanceRemovalDelay")) {
config.set("editInstanceRemovalDelay", editInstanceRemovalDelay);
}
if (!config.contains("secureMode.enabled")) { if (!config.contains("secureMode.enabled")) {
config.set("secureMode.enabled", secureModeEnabled); config.set("secureMode.enabled", secureModeEnabled);
} }
@ -647,6 +666,7 @@ public class MainConfig extends DREConfig {
} }
maxInstances = config.getInt("maxInstances", maxInstances); maxInstances = config.getInt("maxInstances", maxInstances);
editInstanceRemovalDelay = config.getInt("editInstanceRemovalDelay", editInstanceRemovalDelay);
secureModeEnabled = config.getBoolean("secureMode.enabled", secureModeEnabled); secureModeEnabled = config.getBoolean("secureMode.enabled", secureModeEnabled);
openInventories = config.getBoolean("secureMode.openInventories", openInventories); openInventories = config.getBoolean("secureMode.openInventories", openInventories);
dropItems = config.getBoolean("secureMode.dropItems", dropItems); dropItems = config.getBoolean("secureMode.dropItems", dropItems);

View File

@ -143,7 +143,7 @@ public class DEditPlayer extends DInstancePlayer implements EditPlayer {
reset(false); reset(false);
if (editWorld != null) { if (editWorld != null && editWorld.getPlayers().isEmpty()) {
editWorld.save(); editWorld.save();
} }
} }

View File

@ -18,16 +18,20 @@ package de.erethon.dungeonsxl.world;
import de.erethon.commons.compatibility.Version; import de.erethon.commons.compatibility.Version;
import de.erethon.commons.misc.FileUtil; import de.erethon.commons.misc.FileUtil;
import de.erethon.commons.misc.ProgressBar;
import de.erethon.dungeonsxl.DungeonsXL; import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.api.event.world.EditWorldSaveEvent; import de.erethon.dungeonsxl.api.event.world.EditWorldSaveEvent;
import de.erethon.dungeonsxl.api.event.world.EditWorldUnloadEvent; import de.erethon.dungeonsxl.api.event.world.EditWorldUnloadEvent;
import de.erethon.dungeonsxl.api.world.EditWorld; import de.erethon.dungeonsxl.api.world.EditWorld;
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.List;
import org.bukkit.Bukkit; 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;
/** /**
@ -87,7 +91,40 @@ public class DEditWorld extends DInstanceWorld implements EditWorld {
public void save() { public void save() {
EditWorldSaveEvent event = new EditWorldSaveEvent(this); EditWorldSaveEvent event = new EditWorldSaveEvent(this);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
plugin.setLoadingWorld(true);
List<Player> players = getWorld().getPlayers();
kickAllPlayers();
getResource().editWorld = null;
plugin.getInstanceCache().remove(this);
getResource().getSignData().serializeSigns(signs.values());
Bukkit.unloadWorld(getWorld(), true);
new ProgressBar(players, plugin.getMainConfig().getEditInstanceRemovalDelay()) {
@Override
public void onFinish() {
getResource().clearFolder();
FileUtil.copyDir(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
DResourceWorld.deleteUnusedFiles(getResource().getFolder());
FileUtil.removeDir(getFolder());
EditWorld newEditWorld = getResource().getOrInstantiateEditWorld(true);
players.forEach(p -> {
if (p.isOnline()) {
new DEditPlayer(plugin, p, newEditWorld);
}
});
plugin.setLoadingWorld(false);
}
}.send(plugin);
}
public void forceSave() {
EditWorldSaveEvent event = new EditWorldSaveEvent(this);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
} }
@ -116,10 +153,12 @@ public class DEditWorld extends DInstanceWorld implements EditWorld {
kickAllPlayers(); kickAllPlayers();
if (save) { if (save) {
getResource().getSignData().serializeSigns(signs.values());
Bukkit.unloadWorld(getWorld(), true); Bukkit.unloadWorld(getWorld(), true);
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override
public void run() { public void run() {
getResource().clearFolder();
FileUtil.copyDir(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES); FileUtil.copyDir(getFolder(), getResource().getFolder(), DungeonsXL.EXCLUDED_FILES);
DResourceWorld.deleteUnusedFiles(getResource().getFolder()); DResourceWorld.deleteUnusedFiles(getResource().getFolder());
FileUtil.removeDir(getFolder()); FileUtil.removeDir(getFolder());
@ -128,8 +167,12 @@ public class DEditWorld extends DInstanceWorld implements EditWorld {
} }
if (!save) { if (!save) {
Bukkit.unloadWorld(getWorld(), /* SPIGOT-5225 */ !Version.isAtLeast(Version.MC1_14_4)); Bukkit.unloadWorld(getWorld(), /* SPIGOT-5225 */ !Version.isAtLeast(Version.MC1_14_4));
DResourceWorld.deleteUnusedFiles(getResource().getFolder()); new BukkitRunnable() {
FileUtil.removeDir(getFolder()); @Override
public void run() {
FileUtil.removeDir(getFolder());
}
}.runTaskLaterAsynchronously(plugin, 200L);
} }
getResource().editWorld = null; getResource().editWorld = null;

View File

@ -65,7 +65,7 @@ public class DResourceWorld implements ResourceWorld {
config = new WorldConfig(plugin, configFile); config = new WorldConfig(plugin, configFile);
} }
signData = new SignData(new File(folder, "DXLData.data")); signData = new SignData(new File(folder, SignData.FILE_NAME));
} }
public DResourceWorld(DungeonsXL plugin, File folder) { public DResourceWorld(DungeonsXL plugin, File folder) {
@ -78,7 +78,7 @@ public class DResourceWorld implements ResourceWorld {
config = new WorldConfig(plugin, configFile); config = new WorldConfig(plugin, configFile);
} }
signData = new SignData(new File(folder, "DXLData.data")); signData = new SignData(new File(folder, SignData.FILE_NAME));
} }
/* Getters and setters */ /* Getters and setters */
@ -211,6 +211,7 @@ public class DResourceWorld implements ResourceWorld {
if (game) { if (game) {
signData.deserializeSigns((DGameWorld) instance); signData.deserializeSigns((DGameWorld) instance);
instance.getWorld().setAutoSave(false);
} else { } else {
signData.deserializeSigns((DEditWorld) instance); signData.deserializeSigns((DEditWorld) instance);
} }
@ -297,6 +298,19 @@ public class DResourceWorld implements ResourceWorld {
return editWorld; return editWorld;
} }
void clearFolder() {
for (File file : FileUtil.getFilesForFolder(getFolder())) {
if (file.getName().equals(SignData.FILE_NAME)) {
continue;
}
if (file.isDirectory()) {
FileUtil.removeDir(file);
} else {
file.delete();
}
}
}
/** /**
* Removes files that are not needed from a world * Removes files that are not needed from a world
* *

View File

@ -36,6 +36,8 @@ import org.bukkit.block.Sign;
*/ */
public class SignData { public class SignData {
public static final String FILE_NAME = "DXLData.data";
private File file; private File file;
public SignData(File file) { public SignData(File file) {
@ -55,7 +57,7 @@ public class SignData {
} }
public void updateFile(DResourceWorld resource) { public void updateFile(DResourceWorld resource) {
file = new File(resource.getFolder(), "DXLData.data"); file = new File(resource.getFolder(), FILE_NAME);
} }
/** /**