Merge 11c9a06a31
into 17129f68d2
This commit is contained in:
commit
229898c14a
|
@ -355,4 +355,13 @@ public interface MVWorldManager {
|
|||
* @return A collection of world names that are deemed importable.
|
||||
*/
|
||||
Collection<String> getPotentialWorlds();
|
||||
|
||||
/**
|
||||
* Performs the given operation that creates and/or unloads a world. If this operation cannot run because the worlds are being ticked, the operation is delayed until the next tick.
|
||||
*
|
||||
* @param worldName The world being modified.
|
||||
* @param operationName The name of the operation being done.
|
||||
* @param worldModification The operation to perform
|
||||
*/
|
||||
void addOrRemoveWorldSafely(String worldName, String operationName, Runnable worldModification);
|
||||
}
|
||||
|
|
|
@ -40,16 +40,19 @@ public class CloneCommand extends MultiverseCommand {
|
|||
@Override
|
||||
public void runCommand(CommandSender sender, List<String> args) {
|
||||
String oldName = args.get(0);
|
||||
if (!this.worldManager.hasUnloadedWorld(oldName, true)) {
|
||||
String newName = args.get(1);
|
||||
if (!this.worldManager.hasUnloadedWorld(oldName, true)) {
|
||||
// If no world was found, we can't clone.
|
||||
sender.sendMessage("Sorry, Multiverse doesn't know about world " + oldName + ", so we can't clone it!");
|
||||
sender.sendMessage("Check the " + ChatColor.GREEN + "/mv list" + ChatColor.WHITE + " command to verify it is listed.");
|
||||
return;
|
||||
}
|
||||
if (this.plugin.getMVWorldManager().cloneWorld(oldName, args.get(1))) {
|
||||
sender.sendMessage(ChatColor.GREEN + "World cloned!");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "World could NOT be cloned!");
|
||||
}
|
||||
this.worldManager.addOrRemoveWorldSafely(oldName, "clone", () -> {
|
||||
if (this.worldManager.cloneWorld(oldName, newName)) {
|
||||
sender.sendMessage(ChatColor.GREEN + "World cloned!");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "World could NOT be cloned!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,12 +120,17 @@ public class CreateCommand extends MultiverseCommand {
|
|||
return;
|
||||
}
|
||||
}
|
||||
Command.broadcastCommandMessage(sender, "Starting creation of world '" + worldName + "'...");
|
||||
|
||||
if (this.worldManager.addWorld(worldName, environment, seed, type, allowStructures, generator, useSpawnAdjust)) {
|
||||
Command.broadcastCommandMessage(sender, "Complete!");
|
||||
} else {
|
||||
Command.broadcastCommandMessage(sender, "FAILED.");
|
||||
}
|
||||
boolean finalAllowStructures = allowStructures;
|
||||
boolean finalUseSpawnAdjust = useSpawnAdjust;
|
||||
this.worldManager.addOrRemoveWorldSafely(worldName, "create", () -> {
|
||||
Command.broadcastCommandMessage(sender, "Starting creation of world '" + worldName + "'...");
|
||||
|
||||
if (this.worldManager.addWorld(worldName, environment, seed, type, finalAllowStructures, generator, finalUseSpawnAdjust)) {
|
||||
Command.broadcastCommandMessage(sender, "Complete!");
|
||||
} else {
|
||||
Command.broadcastCommandMessage(sender, "FAILED.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -47,7 +47,7 @@ public class DeleteCommand extends MultiverseCommand {
|
|||
private Runnable deleteRunnable(@NotNull CommandSender sender,
|
||||
@NotNull String worldName) {
|
||||
|
||||
return () -> {
|
||||
return () -> this.plugin.getMVWorldManager().addOrRemoveWorldSafely(worldName, "delete", () -> {
|
||||
sender.sendMessage(String.format("Deleting world '%s'...", worldName));
|
||||
if (this.plugin.getMVWorldManager().deleteWorld(worldName)) {
|
||||
sender.sendMessage(String.format("%sWorld %s was deleted!", ChatColor.GREEN, worldName));
|
||||
|
@ -55,6 +55,6 @@ public class DeleteCommand extends MultiverseCommand {
|
|||
}
|
||||
sender.sendMessage(String.format("%sThere was an issue deleting '%s'! Please check console for errors.",
|
||||
ChatColor.RED, worldName));
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,11 +127,14 @@ public class ImportCommand extends MultiverseCommand {
|
|||
sender.sendMessage("That world environment did not exist.");
|
||||
sender.sendMessage("For a list of available world types, type: " + ChatColor.AQUA + "/mvenv");
|
||||
} else {
|
||||
Command.broadcastCommandMessage(sender, String.format("Starting import of world '%s'...", worldName));
|
||||
if (this.worldManager.addWorld(worldName, environment, null, null, null, generator, useSpawnAdjust))
|
||||
Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Complete!");
|
||||
else
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed!");
|
||||
boolean finalUseSpawnAdjust = useSpawnAdjust;
|
||||
this.worldManager.addOrRemoveWorldSafely(worldName, "unload", () -> {
|
||||
Command.broadcastCommandMessage(sender, String.format("Starting import of world '%s'...", worldName));
|
||||
if (this.worldManager.addWorld(worldName, environment, null, null, null, generator, finalUseSpawnAdjust))
|
||||
Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Complete!");
|
||||
else
|
||||
Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed!");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,10 +33,13 @@ public class LoadCommand extends MultiverseCommand {
|
|||
|
||||
@Override
|
||||
public void runCommand(CommandSender sender, List<String> args) {
|
||||
if (this.plugin.getMVWorldManager().loadWorld(args.get(0))) {
|
||||
Command.broadcastCommandMessage(sender, "Loaded world '" + args.get(0) + "'!");
|
||||
} else {
|
||||
sender.sendMessage("Error trying to load world '" + args.get(0) + "'!");
|
||||
}
|
||||
String worldName = args.get(0);
|
||||
this.plugin.getMVWorldManager().addOrRemoveWorldSafely(worldName, "load", () -> {
|
||||
if (this.plugin.getMVWorldManager().loadWorld(worldName)) {
|
||||
Command.broadcastCommandMessage(sender, "Loaded world '" + worldName + "'!");
|
||||
} else {
|
||||
sender.sendMessage("Error trying to load world '" + worldName + "'!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,12 +61,12 @@ public class RegenCommand extends MultiverseCommand {
|
|||
@NotNull String seed,
|
||||
boolean keepGamerules) {
|
||||
|
||||
return () -> {
|
||||
return () -> plugin.getMVWorldManager().addOrRemoveWorldSafely(worldName, "regenerate", () -> {
|
||||
if (this.plugin.getMVWorldManager().regenWorld(worldName, useSeed, randomSeed, seed, keepGamerules)) {
|
||||
sender.sendMessage(ChatColor.GREEN + "World Regenerated!");
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(ChatColor.RED + "World could NOT be regenerated!");
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,10 +33,13 @@ public class RemoveCommand extends MultiverseCommand {
|
|||
|
||||
@Override
|
||||
public void runCommand(CommandSender sender, List<String> args) {
|
||||
if (this.plugin.getMVWorldManager().removeWorldFromConfig(args.get(0))) {
|
||||
sender.sendMessage("World removed from config!");
|
||||
} else {
|
||||
sender.sendMessage("Error trying to remove world from config!");
|
||||
}
|
||||
String worldName = args.get(0);
|
||||
this.plugin.getMVWorldManager().addOrRemoveWorldSafely(worldName, "remove", () -> {
|
||||
if (this.plugin.getMVWorldManager().removeWorldFromConfig(worldName)) {
|
||||
sender.sendMessage("World removed from config!");
|
||||
} else {
|
||||
sender.sendMessage("Error trying to remove world from config!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,10 +33,13 @@ public class UnloadCommand extends MultiverseCommand {
|
|||
|
||||
@Override
|
||||
public void runCommand(CommandSender sender, List<String> args) {
|
||||
if (this.plugin.getMVWorldManager().unloadWorld(args.get(0))) {
|
||||
Command.broadcastCommandMessage(sender, "Unloaded world '" + args.get(0) + "'!");
|
||||
} else {
|
||||
sender.sendMessage("Error trying to unload world '" + args.get(0) + "'!");
|
||||
}
|
||||
String worldName = args.get(0);
|
||||
this.plugin.getMVWorldManager().addOrRemoveWorldSafely(worldName, "unload", () -> {
|
||||
if (this.plugin.getMVWorldManager().unloadWorld(worldName)) {
|
||||
Command.broadcastCommandMessage(sender, "Unloaded world '" + worldName + "'!");
|
||||
} else {
|
||||
sender.sendMessage("Error trying to unload world '" + worldName + "'!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,13 @@ import org.bukkit.generator.ChunkGenerator;
|
|||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -48,7 +51,6 @@ import java.util.Set;
|
|||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -1029,4 +1031,45 @@ public class WorldManager implements MVWorldManager {
|
|||
.map(File::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void addOrRemoveWorldSafely(String worldName, String operationName, Runnable worldModification) {
|
||||
Logging.finest("Checking if it is safe to perform world modification");
|
||||
if (safeToAddOrRemoveWorld()) {
|
||||
// Operation is fine to do now
|
||||
Logging.finest("Clear to modify worlds");
|
||||
worldModification.run();
|
||||
} else {
|
||||
// Operation needs to be delayed until worlds are not being ticked
|
||||
Logging.fine("Worlds were being ticked while attempting to %s %s. Trying again in the next tick", operationName, worldName);
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
worldModification.run();
|
||||
}
|
||||
}.runTask(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean safeToAddOrRemoveWorld(){
|
||||
Logging.finest("Checking for Paper");
|
||||
Method isTickingWorlds;
|
||||
try {
|
||||
isTickingWorlds = Bukkit.class.getMethod("isTickingWorlds");
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Paper fixes aren't active, so it is always considered safe to proceed
|
||||
Logging.finest("Paper fixes inactive");
|
||||
return true;
|
||||
}
|
||||
// Paper fixes are active, and Paper wants us to check Bukkit.isTickingWorlds()
|
||||
Logging.finest("Paper fixes active");
|
||||
try {
|
||||
return !(boolean) isTickingWorlds.invoke(null);
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
// Shouldn't happen, I know I'm using the method correctly
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue