Compare commits

..
26 Commits
Author SHA1 Message Date
Ben Wooandmontlikadani 3e85e42bd0 Update src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java
Co-authored-by: montlikadani <montlikada@gmail.com>
2021-02-18 23:20:13 +08:00
benwoo1110 3f2ec3d40f Refactor clone operation with CloneHelper class. 2020-12-12 10:23:44 +08:00
Alexander Krantz ed80083fe8 Fix null location when teleporting to own playerbed destination. (#2487)
* Fix teleporting to a the calling player's bed

* Change name to my-bed to prevent collisions with player names

* Re-add old player bed for backwards compatibility

* Remove second bed destination name

* Give constant more sensible name
2020-11-27 12:58:11 +08:00
Ben Woo d041e0a8d1 Merge pull request #2490 from benwoo1110/fix-tags
Update issue template with new tags.
2020-11-25 11:44:16 +08:00
benwoo1110 de85be5832 Update issue template with new tags. 2020-11-25 11:41:57 +08:00
Ben Woo 81d59d8bf5 Update issue template to use paste.gg (#2450)
* Update issue template to use paste.gg

* Update to show paste.gg as link
2020-10-27 11:56:18 -04:00
Jeremy Wood 0c2d2f4e0a One more test for the webhook... 2020-10-08 02:38:34 -04:00
Jeremy Wood 3d9108fb48 Minor change to test webhooks on new base branch. 2020-10-08 02:35:30 -04:00
Jeremy Wood 25c616bc32 Bumped version to 4.2.3-SNAPSHOT for continued development. 2020-10-08 02:21:13 -04:00
Jeremy Wood 148187025a Release version 4.2.2. 2020-10-08 00:38:58 -04:00
Jeremy Wood 115b0dc078 Dump full version output in multifile pastes. 2020-10-07 23:52:43 -04:00
Jeremy Wood 78bf6ba3bf Merge pull request #2442 from Multiverse/version_command_typo
Correct a Typo in VersionCommand
2020-10-07 23:33:13 -04:00
Kermina Awad e31c391af4 correct a typo in VersionCommand 2020-10-07 23:15:21 -04:00
Jeremy Wood 6ed4be9a64 Move back to '\n' line separators in version command. 2020-10-07 23:12:50 -04:00
Jeremy Wood d626e7e4b1 Merge pull request #2429 from benwoo1110/green-warning
More noticable warning for deprecated event
2020-10-07 22:41:54 -04:00
Jeremy Wood e7dd4fee51 Merge pull request #2430 from benwoo1110/clone-cleanup
Remove uneeded variables from clone method
2020-10-07 22:41:01 -04:00
Ben Woo 146075de69 Loads unloaded world before deleting (#2431)
* Loads unload world before deleting

Fixes issue where unloaded worlds can't be deleted.

* Missing commit line smh
2020-10-07 22:38:45 -04:00
Jeremy Wood 9fce6c54f6 Merge pull request #2435 from Multiverse/webpaste
Fix Double Prefix when Logging Version Info
2020-10-07 22:37:22 -04:00
Ben Woo f189eb3b7e Fix issue template label (#2437)
* Fix issue template label

* Remove "type: " from label
2020-10-07 22:32:32 -04:00
Kermina Awad 2d4fe301cf fix double prefix when logging version info 2020-10-06 16:26:20 -04:00
Jeremy Wood e5fe1fe565 Bump version to 4.2.2-SNAPSHOT for continued development. 2020-10-06 15:46:37 -04:00
Jeremy Wood 83010f1a28 Release version 4.2.1. 2020-10-06 15:08:13 -04:00
Jeremy Wood 864e50e38c Add TestingMode util. 2020-10-06 15:07:56 -04:00
Jeremy Wood 0a99258f3e Bump version to 4.2.1-SNAPSHOT for continued development. 2020-10-06 15:01:42 -04:00
benwoo1110 b345baf20e Remove uneeded variables from clone method 2020-10-06 21:12:18 +08:00
benwoo1110 d532052c7b More noticable warning for deprecated event
Add green color to the warning
2020-10-06 20:47:41 +08:00
11 changed files with 303 additions and 187 deletions

No files matched your search

+2 -2
View File
@@ -2,7 +2,7 @@
name: ❓ Help!
about: Encountered a problem with Multiverse-Core? Not sure how to fix it?
title: ''
labels: 'type: Assistance'
labels: 'Type: Assistance'
assignees: ''
---
@@ -40,7 +40,7 @@ If you're happy to wait (or you were sent here from Discord), read on:
* **Server version:** <!-- Insert output of `/version` command -->
* **Full output of `/mv version -b`:** <!-- Replace this with the command output's https://pastebin.com link -->
* **Full output of `/mv version -p`:** <!-- Replace this with the command output's https://paste.gg/ link -->
* **Server log:** <!-- Upload `logs/latest.log` to https://gist.github.com/ -->
+2 -2
View File
@@ -2,7 +2,7 @@
name: 🐛 Report a Bug
about: Report a Multiverse-Core bug. Only use this if you're 100% sure it's something wrong with Multiverse-Core - otherwise, try "Help!".
title: ''
labels: 'type: Bug'
labels: 'Bug: Unconfirmed'
assignees: ''
---
@@ -39,7 +39,7 @@ If you are reporting a bug, please follow the following steps:
* **Server version:** <!-- Insert output of `/version` command -->
* **Full output of `/mv version -b`:** <!-- Replace this with the command output's https://pastebin.com link -->
* **Full output of `/mv version -p`:** <!-- Replace this with the command output's https://paste.gg/ link -->
* **Server log:** <!-- Upload `logs/latest.log` to https://gist.github.com/ -->
+1 -1
View File
@@ -2,7 +2,7 @@
name: 💡 Request a Feature
about: Suggest a feature you want to see in Multiverse-Core!
title: ''
labels: 'type: Suggestion'
labels: 'Type: Idea'
assignees: ''
---
+1 -1
View File
@@ -13,4 +13,4 @@ Copyright (c) 2011, The Multiverse Team All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the The Multiverse Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+1 -1
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.onarandombox.multiversecore</groupId>
<artifactId>Multiverse-Core</artifactId>
<version>4.2.0</version>
<version>4.2.3-SNAPSHOT</version>
<name>Multiverse-Core</name>
<description>World Management Plugin</description>
<properties>
@@ -93,6 +93,7 @@ import com.onarandombox.MultiverseCore.utils.MVMessaging;
import com.onarandombox.MultiverseCore.utils.MVPermissions;
import com.onarandombox.MultiverseCore.utils.MVPlayerSession;
import com.onarandombox.MultiverseCore.utils.MaterialConverter;
import com.onarandombox.MultiverseCore.utils.TestingMode;
import com.onarandombox.MultiverseCore.utils.metrics.MetricsConfigurator;
import com.onarandombox.MultiverseCore.utils.SimpleBlockSafety;
import com.onarandombox.MultiverseCore.utils.SimpleLocationManipulation;
@@ -343,7 +344,9 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
}
private void setupMetrics() {
MetricsConfigurator.configureMetrics(this);
if (TestingMode.isDisabled()) {
MetricsConfigurator.configureMetrics(this);
}
}
/**
@@ -380,7 +383,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
pm.registerEvents(this.entityListener, this);
pm.registerEvents(this.weatherListener, this);
pm.registerEvents(this.portalListener, this);
log(Level.INFO, "We are aware of the warning about the deprecated event. There is no alternative that allows us to do what we need to do. The performance impact is negligible.");
log(Level.INFO, ChatColor.GREEN + "We are aware of the warning about the deprecated event. There is no alternative that allows us to do what we need to do and performance impact is negligible. It is safe to ignore.");
pm.registerEvents(this.worldListener, this);
pm.registerEvents(new MVMapListener(this), this);
}
@@ -26,12 +26,7 @@ import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -55,58 +50,58 @@ public class VersionCommand extends MultiverseCommand {
}
private String getLegacyString() {
return "[Multiverse-Core] Multiverse-Core Version: " + this.plugin.getDescription().getVersion() + System.lineSeparator()
+ "[Multiverse-Core] Bukkit Version: " + this.plugin.getServer().getVersion() + System.lineSeparator()
+ "[Multiverse-Core] Loaded Worlds: " + this.plugin.getMVWorldManager().getMVWorlds() + System.lineSeparator()
+ "[Multiverse-Core] Multiverse Plugins Loaded: " + this.plugin.getPluginCount() + System.lineSeparator()
+"[Multiverse-Core] Economy being used: " + plugin.getEconomist().getEconomyName() + System.lineSeparator()
+ "[Multiverse-Core] Permissions Plugin: " + this.plugin.getMVPerms().getType() + System.lineSeparator()
+ "[Multiverse-Core] Dumping Config Values: (version " + this.plugin.getMVConfig().getVersion() + ")" + System.lineSeparator()
+ "[Multiverse-Core] enforceaccess: " + plugin.getMVConfig().getEnforceAccess() + System.lineSeparator()
+ "[Multiverse-Core] prefixchat: " + plugin.getMVConfig().getPrefixChat() + System.lineSeparator()
+ "[Multiverse-Core] prefixchatformat: " + plugin.getMVConfig().getPrefixChatFormat() + System.lineSeparator()
+ "[Multiverse-Core] useasyncchat: " + plugin.getMVConfig().getUseAsyncChat() + System.lineSeparator()
+ "[Multiverse-Core] teleportintercept: " + plugin.getMVConfig().getTeleportIntercept() + System.lineSeparator()
+ "[Multiverse-Core] firstspawnoverride: " + plugin.getMVConfig().getFirstSpawnOverride() + System.lineSeparator()
+ "[Multiverse-Core] displaypermerrors: " + plugin.getMVConfig().getDisplayPermErrors() + System.lineSeparator()
+ "[Multiverse-Core] globaldebug: " + plugin.getMVConfig().getGlobalDebug() + System.lineSeparator()
+ "[Multiverse-Core] silentstart: " + plugin.getMVConfig().getSilentStart() + System.lineSeparator()
+ "[Multiverse-Core] messagecooldown: " + plugin.getMessaging().getCooldown() + System.lineSeparator()
+ "[Multiverse-Core] version: " + plugin.getMVConfig().getVersion() + System.lineSeparator()
+ "[Multiverse-Core] firstspawnworld: " + plugin.getMVConfig().getFirstSpawnWorld() + System.lineSeparator()
+ "[Multiverse-Core] teleportcooldown: " + plugin.getMVConfig().getTeleportCooldown() + System.lineSeparator()
+ "[Multiverse-Core] defaultportalsearch: " + plugin.getMVConfig().isUsingDefaultPortalSearch() + System.lineSeparator()
+ "[Multiverse-Core] portalsearchradius: " + plugin.getMVConfig().getPortalSearchRadius() + System.lineSeparator()
+ "[Multiverse-Core] autopurge: " + plugin.getMVConfig().isAutoPurgeEnabled() + System.lineSeparator()
+ "[Multiverse-Core] Special Code: FRN002" + System.lineSeparator();
return "[Multiverse-Core] Multiverse-Core Version: " + this.plugin.getDescription().getVersion() + '\n'
+ "[Multiverse-Core] Bukkit Version: " + this.plugin.getServer().getVersion() + '\n'
+ "[Multiverse-Core] Loaded Worlds: " + this.plugin.getMVWorldManager().getMVWorlds() + '\n'
+ "[Multiverse-Core] Multiverse Plugins Loaded: " + this.plugin.getPluginCount() + '\n'
+"[Multiverse-Core] Economy being used: " + plugin.getEconomist().getEconomyName() + '\n'
+ "[Multiverse-Core] Permissions Plugin: " + this.plugin.getMVPerms().getType() + '\n'
+ "[Multiverse-Core] Dumping Config Values: (version " + this.plugin.getMVConfig().getVersion() + ")" + '\n'
+ "[Multiverse-Core] enforceaccess: " + plugin.getMVConfig().getEnforceAccess() + '\n'
+ "[Multiverse-Core] prefixchat: " + plugin.getMVConfig().getPrefixChat() + '\n'
+ "[Multiverse-Core] prefixchatformat: " + plugin.getMVConfig().getPrefixChatFormat() + '\n'
+ "[Multiverse-Core] useasyncchat: " + plugin.getMVConfig().getUseAsyncChat() + '\n'
+ "[Multiverse-Core] teleportintercept: " + plugin.getMVConfig().getTeleportIntercept() + '\n'
+ "[Multiverse-Core] firstspawnoverride: " + plugin.getMVConfig().getFirstSpawnOverride() + '\n'
+ "[Multiverse-Core] displaypermerrors: " + plugin.getMVConfig().getDisplayPermErrors() + '\n'
+ "[Multiverse-Core] globaldebug: " + plugin.getMVConfig().getGlobalDebug() + '\n'
+ "[Multiverse-Core] silentstart: " + plugin.getMVConfig().getSilentStart() + '\n'
+ "[Multiverse-Core] messagecooldown: " + plugin.getMessaging().getCooldown() + '\n'
+ "[Multiverse-Core] version: " + plugin.getMVConfig().getVersion() + '\n'
+ "[Multiverse-Core] firstspawnworld: " + plugin.getMVConfig().getFirstSpawnWorld() + '\n'
+ "[Multiverse-Core] teleportcooldown: " + plugin.getMVConfig().getTeleportCooldown() + '\n'
+ "[Multiverse-Core] defaultportalsearch: " + plugin.getMVConfig().isUsingDefaultPortalSearch() + '\n'
+ "[Multiverse-Core] portalsearchradius: " + plugin.getMVConfig().getPortalSearchRadius() + '\n'
+ "[Multiverse-Core] autopurge: " + plugin.getMVConfig().isAutoPurgeEnabled() + '\n'
+ "[Multiverse-Core] Special Code: FRN002" + '\n';
}
private String getMarkdownString() {
return "# Multiverse-Core" + System.lineSeparator()
+ "## Overview" + System.lineSeparator()
+ "| Name | Value |" + System.lineSeparator()
+ "| --- | --- |" + System.lineSeparator()
+ "| Multiverse-Core Version | `" + this.plugin.getDescription().getVersion() + "` |" + System.lineSeparator()
+ "| Bukkit Version | `" + this.plugin.getServer().getVersion() + "` |" + System.lineSeparator()
+ "| Loaded Worlds | `" + this.plugin.getMVWorldManager().getMVWorlds() + "` |" + System.lineSeparator()
+ "| Multiverse Plugins Loaded | `" + this.plugin.getPluginCount() + "` |" + System.lineSeparator()
+ "| Economy being used | `" + plugin.getEconomist().getEconomyName() + "` |" + System.lineSeparator()
+ "| Permissions Plugin | `" + this.plugin.getMVPerms().getType() + "` |" + System.lineSeparator()
+ "## Parsed Config" + System.lineSeparator()
+ "These are what Multiverse thought the in-memory values of the config were." + System.lineSeparator() + System.lineSeparator()
+ "| Config Key | Value |" + System.lineSeparator()
+ "| --- | --- |" + System.lineSeparator()
+ "| version | `" + this.plugin.getMVConfig().getVersion() + "` |" + System.lineSeparator()
+ "| messagecooldown | `" + plugin.getMessaging().getCooldown() + "` |" + System.lineSeparator()
+ "| teleportcooldown | `" + plugin.getMVConfig().getTeleportCooldown() + "` |" + System.lineSeparator()
+ "| worldnameprefix | `" + plugin.getMVConfig().getPrefixChat() + "` |" + System.lineSeparator()
+ "| worldnameprefixFormat | `" + plugin.getMVConfig().getPrefixChatFormat() + "` |" + System.lineSeparator()
+ "| enforceaccess | `" + plugin.getMVConfig().getEnforceAccess() + "` |" + System.lineSeparator()
+ "| displaypermerrors | `" + plugin.getMVConfig().getDisplayPermErrors() + "` |" + System.lineSeparator()
+ "| teleportintercept | `" + plugin.getMVConfig().getTeleportIntercept() + "` |" + System.lineSeparator()
+ "| firstspawnoverride | `" + plugin.getMVConfig().getFirstSpawnOverride() + "` |" + System.lineSeparator()
+ "| firstspawnworld | `" + plugin.getMVConfig().getFirstSpawnWorld() + "` |" + System.lineSeparator()
+ "| debug | `" + plugin.getMVConfig().getGlobalDebug() + "` |" + System.lineSeparator();
return "# Multiverse-Core" + '\n'
+ "## Overview" + '\n'
+ "| Name | Value |" + '\n'
+ "| --- | --- |" + '\n'
+ "| Multiverse-Core Version | `" + this.plugin.getDescription().getVersion() + "` |" + '\n'
+ "| Bukkit Version | `" + this.plugin.getServer().getVersion() + "` |" + '\n'
+ "| Loaded Worlds | `" + this.plugin.getMVWorldManager().getMVWorlds() + "` |" + '\n'
+ "| Multiverse Plugins Loaded | `" + this.plugin.getPluginCount() + "` |" + '\n'
+ "| Economy being used | `" + plugin.getEconomist().getEconomyName() + "` |" + '\n'
+ "| Permissions Plugin | `" + this.plugin.getMVPerms().getType() + "` |" + '\n'
+ "## Parsed Config" + '\n'
+ "These are what Multiverse thought the in-memory values of the config were." + "\n\n"
+ "| Config Key | Value |" + '\n'
+ "| --- | --- |" + '\n'
+ "| version | `" + this.plugin.getMVConfig().getVersion() + "` |" + '\n'
+ "| messagecooldown | `" + plugin.getMessaging().getCooldown() + "` |" + '\n'
+ "| teleportcooldown | `" + plugin.getMVConfig().getTeleportCooldown() + "` |" + '\n'
+ "| worldnameprefix | `" + plugin.getMVConfig().getPrefixChat() + "` |" + '\n'
+ "| worldnameprefixFormat | `" + plugin.getMVConfig().getPrefixChatFormat() + "` |" + '\n'
+ "| enforceaccess | `" + plugin.getMVConfig().getEnforceAccess() + "` |" + '\n'
+ "| displaypermerrors | `" + plugin.getMVConfig().getDisplayPermErrors() + "` |" + '\n'
+ "| teleportintercept | `" + plugin.getMVConfig().getTeleportIntercept() + "` |" + '\n'
+ "| firstspawnoverride | `" + plugin.getMVConfig().getFirstSpawnOverride() + "` |" + '\n'
+ "| firstspawnworld | `" + plugin.getMVConfig().getFirstSpawnWorld() + "` |" + '\n'
+ "| debug | `" + plugin.getMVConfig().getGlobalDebug() + "` |" + '\n';
}
private void addVersionInfoToEvent(MVVersionEvent event) {
@@ -114,15 +109,16 @@ public class VersionCommand extends MultiverseCommand {
event.appendVersionInfo(this.getLegacyString());
// add the legacy file, but as markdown so it's readable
event.putDetailedVersionInfo("version.md", this.getMarkdownString());
// TODO Readd this in 5.0.0
// event.putDetailedVersionInfo("version.md", this.getMarkdownString());
// add config.yml
File configFile = new File(this.plugin.getDataFolder(), "config.yml");
event.putDetailedVersionInfo("version.md", configFile);
event.putDetailedVersionInfo("multiverse-core/config.yml", configFile);
// add worlds.yml
File worldsFile = new File(this.plugin.getDataFolder(), "worlds.yml");
event.putDetailedVersionInfo("version.md", worldsFile);
event.putDetailedVersionInfo("multiverse-core/worlds.yml", worldsFile);
}
@Override
@@ -138,18 +134,20 @@ public class VersionCommand extends MultiverseCommand {
this.plugin.getServer().getPluginManager().callEvent(versionEvent);
if (CommandHandler.hasFlag("--include-plugin-list", args)) {
versionEvent.appendVersionInfo(System.lineSeparator() + "Plugins: " + getPluginList());
versionEvent.appendVersionInfo('\n' + "Plugins: " + getPluginList());
versionEvent.putDetailedVersionInfo("plugins.txt", "Plugins: " + getPluginList());
}
final String versionInfo = versionEvent.getVersionInfo();
versionEvent.putDetailedVersionInfo("version.txt", versionInfo);
final Map<String, String> files = versionEvent.getDetailedVersionInfo();
// log to console
String[] lines = versionInfo.split(System.lineSeparator());
String[] lines = versionInfo.split("\\r?\\n");
for (String line : lines) {
if (!line.isEmpty()) {
Logging.info(line);
this.plugin.getServer().getLogger().info(line);
}
}
@@ -23,7 +23,7 @@ import org.bukkit.util.Vector;
* A bed-{@link MVDestination}.
*/
public class BedDestination implements MVDestination {
public static final String OLD_BED_STRING = "b:playerbed";
public static final String OWN_BED_STRING = "playerbed";
private String playername = "";
private boolean isValid;
private Location knownBedLoc;
@@ -46,11 +46,11 @@ public class BedDestination implements MVDestination {
boolean validFormat = split.length >= 1 && split.length <= 2 && split[0].equals(this.getIdentifier());
OfflinePlayer p = Bukkit.getOfflinePlayer(split[1]);
boolean validPlayer = (p != null);
boolean validPlayer = p.getName() != null && !p.getName().equals(OWN_BED_STRING);
if (validFormat && validPlayer) this.playername = p.getName();
this.isValid = destination.equals(OLD_BED_STRING) || (validFormat && validPlayer);
this.isValid = destination.equals("b:" + OWN_BED_STRING) || (validFormat && validPlayer);
return this.isValid;
}
@@ -136,6 +136,6 @@ public class BedDestination implements MVDestination {
@Override
public String toString() {
return playername.isEmpty() ? OLD_BED_STRING : ("b:" + playername);
return "b:" + (playername.isEmpty() ? OWN_BED_STRING : playername);
}
}
@@ -0,0 +1,18 @@
package com.onarandombox.MultiverseCore.utils;
/**
* A utility class that enables automated tests to flag Multiverse for testing. This allows Multiverse to not perform
* certain behaviors such as enabled stats uploads.
*/
public class TestingMode {
private static boolean enabled = false;
public static void enable() {
enabled = true;
}
public static boolean isDisabled() {
return !enabled;
}
}
@@ -47,7 +47,6 @@ import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -63,6 +62,8 @@ public class WorldManager implements MVWorldManager {
private Map<String, String> defaultGens;
private String firstSpawn;
private static final List<String> CLONE_IGNORE_FILES = Arrays.asList("session.lock", "uid.dat");
public WorldManager(MultiverseCore core) {
this.plugin = core;
this.worldsFromTheConfig = new HashMap<String, WorldProperties>();
@@ -95,6 +96,190 @@ public class WorldManager implements MVWorldManager {
}
}
/**
* Makes cloning easier to understand and manage.
*/
private class CloneHelper {
private String oldName;
private String newName;
private File oldWorldFile;
private File newWorldFile;
private MultiverseWorld oldWorld;
public CloneHelper(String oldName, String newName) {
this.oldName = oldName;
this.newName = newName;
}
/**
* The clone operation.
*
* @return True if clone is successful, false otherwise.
*/
public boolean run() {
if (!validCloneParameters()) {
Logging.warning("Invalid clone parameters");
return false;
}
initWorldFiles();
if (newWorldFile.exists()) {
Logging.warning("Folder for new world '%s' already exists", newName);
return false;
}
oldWorld = getMVWorld(oldName);
if (!isOldWorldLoadable()) {
Logging.severe("Old world '%s' is not loadable", oldName);
return false;
}
boolean wasAutoSave = manuallySaveWorld();
if (!copyWorldFolder()) {
return false;
}
revertBackAutoSave(wasAutoSave);
return initNewCloneWorld();
}
/**
* Ensure that world with oldName can be clone to a world called newName.
*
* @return True if parameters are valid, otherwise false.
*/
private boolean validCloneParameters() {
String originalOldName = oldName;
if (!isWorldFromConfig(oldName)) {
oldName = getWorldByAliasFromConfig(oldName);
}
if (oldName == null) {
Logging.warning("Old world '%s' does not exist", originalOldName);
return false;
}
if (isWorldFromConfig(newName)) {
Logging.warning("New world '%s' already exists", newName);
return false;
}
if (!isValidWorldName(newName)) {
Logging.warning("New world name '%s' is invalid", newName);
return false;
}
return true;
}
/**
* Get world folders from world container.
*/
private void initWorldFiles() {
oldWorldFile = new File(plugin.getServer().getWorldContainer(), oldName);
newWorldFile = new File(plugin.getServer().getWorldContainer(), newName);
}
/**
* Ensure that old world can be loaded and saved properly.
*
* @return True if old world can be loaded successfully, false otherwise.
*/
private boolean isOldWorldLoadable() {
if (oldWorld != null) {
return true;
}
Logging.fine("Old world '%s' is currently unloaded. Attempting to load it...", oldName);
WorldProperties props = worldsFromTheConfig.get(oldName);
boolean wasLoadSpawn = worldsFromTheConfig.get(oldName).isKeepingSpawnInMemory();
if (wasLoadSpawn) {
props.setKeepSpawnInMemory(false);
}
if (!loadWorld(oldName)) {
Logging.severe("Failed to load the old world '%s'", oldName);
return false;
}
getMVWorld(oldName).getCBWorld().setAutoSave(false);
if (!unloadWorld(oldName, true)) {
Logging.severe("Failed to unload the old world '%S'", oldName);
return false;
}
if (wasLoadSpawn) {
props.setKeepSpawnInMemory(true);
}
return true;
}
/**
* Duplicating old world folder to the new world folder.
*
* @return True if copy process was successful, false otherwise.
*/
private boolean copyWorldFolder() {
Logging.fine("Copying files for world '%s'", oldName);
if (!FileUtils.copyFolder(oldWorldFile, newWorldFile, CLONE_IGNORE_FILES, Logging.getLogger()) || !newWorldFile.exists()) {
Logging.severe("Failed to copy files for world '%s', see the log info", newName);
return false;
}
Logging.fine("Succeeded at copying files");
return true;
}
/**
* Ensure world is save being copying world files.
*
* @return Previous auto-save setting for the old world.
*/
private boolean manuallySaveWorld() {
if (oldWorld != null && oldWorld.getCBWorld().isAutoSave()) {
Logging.config("Saving world '%s'", oldName);
oldWorld.getCBWorld().setAutoSave(false);
oldWorld.getCBWorld().save();
return true;
}
return false;
}
private void revertBackAutoSave(boolean wasAutoSave) {
if (oldWorld != null && wasAutoSave) {
Logging.fine("Revert back to enabling auto-save");
oldWorld.getCBWorld().setAutoSave(true);
}
}
/**
* Initialize new properties with old ones.
*/
private void copyPropertiesToNewWorld() {
WorldProperties newProps = new WorldProperties();
newProps.copyValues(worldsFromTheConfig.get(oldName));
newProps.setAlias(""); // don't keep the alias the same -- that would be useless
worldsFromTheConfig.put(newName, newProps);
}
/**
* Load up the newly copied clone world.
*/
private boolean initNewCloneWorld() {
copyPropertiesToNewWorld();
if (!saveWorldsConfig()) {
Logging.severe("Failed to save worlds.yml");
return false;
}
if (!doLoad(newName)) {
Logging.severe("Failed to load the cloned world '" + newName + "'");
return false;
}
Logging.fine("Succeeded at loading cloned world '" + newName + "'");
return true;
}
}
/**
* {@inheritDoc}
* @deprecated Use {@link #cloneWorld(String, String)} instead.
@@ -110,119 +295,7 @@ public class WorldManager implements MVWorldManager {
*/
@Override
public boolean cloneWorld(String oldName, String newName) {
// Make sure we already know about the old world and that we don't
// already know about the new world.
if (!this.worldsFromTheConfig.containsKey(oldName)) {
for (Map.Entry<String, WorldProperties> entry : this.worldsFromTheConfig.entrySet()) {
if (oldName.equals(entry.getValue().getAlias())) {
oldName = entry.getKey();
break;
}
}
if (!this.worldsFromTheConfig.containsKey(oldName)) {
Logging.warning("Old world '%s' does not exist", oldName);
return false;
}
}
if (this.isMVWorld(newName)) {
Logging.warning("New world '%s' already exists", newName);
return false;
}
// Check for valid world name
if (!(isValidWorldName(oldName) && isValidWorldName(newName))) {
return false;
}
final File oldWorldFile = new File(this.plugin.getServer().getWorldContainer(), oldName);
final File newWorldFile = new File(this.plugin.getServer().getWorldContainer(), newName);
final List<String> ignoreFiles = new ArrayList<>(Arrays.asList("session.lock", "uid.dat"));
// Make sure the new world doesn't exist outside of multiverse.
if (newWorldFile.exists()) {
Logging.warning("File for new world '%s' already exists", newName);
return false;
}
// Load the old world... but just the metadata.
boolean wasJustLoaded = false;
boolean wasLoadSpawn = false;
if (this.plugin.getServer().getWorld(oldName) == null) {
wasJustLoaded = true;
WorldProperties props = this.worldsFromTheConfig.get(oldName);
wasLoadSpawn = props.isKeepingSpawnInMemory();
if (wasLoadSpawn) {
// No chunks please.
props.setKeepSpawnInMemory(false);
}
if (!this.loadWorld(oldName)) {
return false;
}
this.plugin.getServer().getWorld(oldName).setAutoSave(false);
}
// Grab a bit of metadata from the old world.
MVWorld oldWorld = (MVWorld) getMVWorld(oldName);
Environment environment = oldWorld.getEnvironment();
String seedString = oldWorld.getSeed() + "";
WorldType worldType = oldWorld.getWorldType();
Boolean generateStructures = oldWorld.getCBWorld().canGenerateStructures();
String generator = oldWorld.getGenerator();
boolean useSpawnAdjust = oldWorld.getAdjustSpawn();
// Don't need the loaded world anymore.
if (wasJustLoaded) {
this.unloadWorld(oldName, true);
oldWorld = null;
if (wasLoadSpawn) {
this.worldsFromTheConfig.get(oldName).setKeepSpawnInMemory(true);
}
}
boolean wasAutoSave = false;
if (oldWorld != null && oldWorld.getCBWorld().isAutoSave()) {
wasAutoSave = true;
Logging.config("Saving world '%s'", oldName);
oldWorld.getCBWorld().setAutoSave(false);
oldWorld.getCBWorld().save();
}
Logging.config("Copying files for world '%s'", oldName);
if (!FileUtils.copyFolder(oldWorldFile, newWorldFile, ignoreFiles, Logging.getLogger())) {
Logging.warning("Failed to copy files for world '%s', see the log info", newName);
return false;
}
if (oldWorld != null && wasAutoSave) {
oldWorld.getCBWorld().setAutoSave(true);
}
if (newWorldFile.exists()) {
Logging.fine("Succeeded at copying files");
// initialize new properties with old ones
WorldProperties newProps = new WorldProperties();
newProps.copyValues(this.worldsFromTheConfig.get(oldName));
// don't keep the alias the same -- that would be useless
newProps.setAlias("");
// store the new properties in worlds config map
this.worldsFromTheConfig.put(newName, newProps);
// save the worlds config to disk (worlds.yml)
if (!saveWorldsConfig()) {
this.plugin.log(Level.SEVERE, "Failed to save worlds.yml");
return false;
}
// actually load the world
if (doLoad(newName)) {
this.plugin.log(Level.FINE, "Succeeded at loading cloned world '" + newName + "'");
return true;
}
this.plugin.log(Level.SEVERE, "Failed to load the cloned world '" + newName + "'");
return false;
}
Logging.warning("Failed to copy files for world '%s', see the log info", newName);
return false;
return new CloneHelper(oldName, newName).run();
}
/**
@@ -525,6 +598,13 @@ public class WorldManager implements MVWorldManager {
*/
@Override
public boolean deleteWorld(String name, boolean removeFromConfig, boolean deleteWorldFolder) {
if (this.hasUnloadedWorld(name, false)) {
// Attempt to load if unloaded so we can actually delete the world
if (!this.doLoad(name)) {
return false;
}
}
World world = this.plugin.getServer().getWorld(name);
if (world == null) {
// We can only delete loaded worlds
@@ -696,6 +776,19 @@ public class WorldManager implements MVWorldManager {
return false;
}
private boolean isWorldFromConfig(String name) {
return this.worldsFromTheConfig.containsKey(name);
}
private String getWorldByAliasFromConfig(String name) {
return this.worldsFromTheConfig.entrySet()
.stream()
.filter(worldEntry -> name.equals(worldEntry.getValue().getAlias()))
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
}
/**
* {@inheritDoc}
*/
@@ -937,6 +1030,9 @@ public class WorldManager implements MVWorldManager {
return this.configWorlds;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasUnloadedWorld(String name, boolean includeLoaded) {
if (getMVWorld(name) != null) {
@@ -64,6 +64,7 @@ public class TestInstanceCreator {
public static final File worldsDirectory = new File("bin/test/server");
public boolean setUp() {
TestingMode.enable();
try {
pluginDirectory.mkdirs();
assertTrue(pluginDirectory.exists());