diff --git a/src/main/java/org/mvplugins/multiverse/core/MultiverseCore.java b/src/main/java/org/mvplugins/multiverse/core/MultiverseCore.java
index 5b6d61de..a8b2460c 100644
--- a/src/main/java/org/mvplugins/multiverse/core/MultiverseCore.java
+++ b/src/main/java/org/mvplugins/multiverse/core/MultiverseCore.java
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.anchor.AnchorManager;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
import org.mvplugins.multiverse.core.api.MVCore;
import org.mvplugins.multiverse.core.commands.CoreCommand;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
diff --git a/src/main/java/org/mvplugins/multiverse/core/api/DestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/api/DestinationInstance.java
deleted file mode 100644
index ddc9bb64..00000000
--- a/src/main/java/org/mvplugins/multiverse/core/api/DestinationInstance.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.mvplugins.multiverse.core.api;
-
-import org.bukkit.Location;
-import org.bukkit.entity.Entity;
-import org.bukkit.util.Vector;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public interface DestinationInstance {
- /**
- * Gets the exact location to teleport an entity to.
- *
- * @param teleportee The entity to teleport.
- * @return The location to teleport to.
- */
- @Nullable Location getLocation(@NotNull Entity teleportee);
-
- /**
- * Gets the velocity to apply to an entity after teleporting.
- *
- * @param teleportee The entity to teleport.
- * @return A vector representing the speed/direction the player should travel when arriving at the destination.
- */
- @Nullable Vector getVelocity(@NotNull Entity teleportee);
-
- /**
- * Gets the permission suffix to check for when teleporting to this destination.
- * This is used for finer per world/player permissions, such as "multiverse.teleport.self.worldname".
- *
- *
For example, if the destination is "w:world", the permission suffix is "world".
- *
- * @return The permission suffix.
- */
- @Nullable String getFinerPermissionSuffix();
-
- /**
- * Serialises the destination instance to a savable string.
- *
- * This is used when plugins save destinations to configuration,
- * and when the destination is displayed to the user.
- *
- * @return The serialised destination instance.
- */
- @NotNull String serialise();
-}
diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/CheckCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/CheckCommand.java
index 5310c5b7..9e75633b 100644
--- a/src/main/java/org/mvplugins/multiverse/core/commands/CheckCommand.java
+++ b/src/main/java/org/mvplugins/multiverse/core/commands/CheckCommand.java
@@ -13,9 +13,8 @@ import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
-import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
@Service
@@ -45,7 +44,7 @@ class CheckCommand extends CoreCommand {
@Syntax("")
@Description("{@@mv-core.check.destination.description}")
- ParsedDestination> destination) {
+ DestinationInstance, ?> destination) {
issuer.sendInfo(MVCorei18n.CHECK_CHECKING,
"{player}", player.getName(),
"{destination}", destination.toString());
diff --git a/src/main/java/org/mvplugins/multiverse/core/commands/TeleportCommand.java b/src/main/java/org/mvplugins/multiverse/core/commands/TeleportCommand.java
index 398c6d34..0cab796a 100644
--- a/src/main/java/org/mvplugins/multiverse/core/commands/TeleportCommand.java
+++ b/src/main/java/org/mvplugins/multiverse/core/commands/TeleportCommand.java
@@ -17,8 +17,7 @@ import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.MVCommandIssuer;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
-import org.mvplugins.multiverse.core.commandtools.MultiverseCommand;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.permissions.CorePermissionsChecker;
import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
import org.mvplugins.multiverse.core.utils.MVCorei18n;
@@ -55,7 +54,7 @@ class TeleportCommand extends CoreCommand {
@Syntax("")
@Description("{@@mv-core.teleport.destination.description}")
- ParsedDestination> destination) {
+ DestinationInstance, ?> destination) {
// TODO: Add warning if teleporting too many players at once.
String playerName = players.length == 1
diff --git a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java
index 63b9f69e..b1a0ff13 100644
--- a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java
+++ b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandCompletions.java
@@ -28,8 +28,8 @@ import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
import org.mvplugins.multiverse.core.configuration.handle.PropertyModifyAction;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.MultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
@@ -68,7 +68,7 @@ class MVCommandCompletions extends PaperCommandCompletions {
registerAsyncCompletion("mvworldpropsvalue", this::suggestMVWorldPropsValue);
registerStaticCompletion("propsmodifyaction", suggestEnums(PropertyModifyAction.class));
- setDefaultCompletion("destinations", ParsedDestination.class);
+ setDefaultCompletion("destinations", DestinationInstance.class);
setDefaultCompletion("difficulties", Difficulty.class);
setDefaultCompletion("environments", World.Environment.class);
setDefaultCompletion("flags", String[].class);
diff --git a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java
index e12c54b3..fb12bbc0 100644
--- a/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java
+++ b/src/main/java/org/mvplugins/multiverse/core/commandtools/MVCommandContexts.java
@@ -16,8 +16,8 @@ import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.commandtools.context.GameRuleValue;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.display.filters.ContentFilter;
import org.mvplugins.multiverse.core.display.filters.DefaultContentFilter;
import org.mvplugins.multiverse.core.display.filters.RegexContentFilter;
@@ -49,7 +49,7 @@ class MVCommandContexts extends PaperCommandContexts {
registerIssuerOnlyContext(BukkitCommandIssuer.class, BukkitCommandExecutionContext::getIssuer);
registerIssuerOnlyContext(MVCommandIssuer.class, this::parseMVCommandIssuer);
registerOptionalContext(ContentFilter.class, this::parseContentFilter);
- registerContext(ParsedDestination.class, this::parseDestination);
+ registerContext(DestinationInstance.class, this::parseDestination);
registerContext(GameRule.class, this::parseGameRule);
registerContext(GameRuleValue.class, this::parseGameRuleValue);
registerIssuerAwareContext(LoadedMultiverseWorld.class, this::parseLoadedMultiverseWorld);
@@ -74,18 +74,14 @@ class MVCommandContexts extends PaperCommandContexts {
return RegexContentFilter.fromString(filterString);
}
- private ParsedDestination> parseDestination(BukkitCommandExecutionContext context) {
+ private DestinationInstance, ?> parseDestination(BukkitCommandExecutionContext context) {
String destination = context.popFirstArg();
if (Strings.isNullOrEmpty(destination)) {
throw new InvalidCommandArgument("No destination specified.");
}
- ParsedDestination> parsedDestination = destinationsProvider.parseDestination(destination);
- if (parsedDestination == null) {
- throw new InvalidCommandArgument("The destination " + destination + " is not valid.");
- }
-
- return parsedDestination;
+ return destinationsProvider.parseDestination(destination)
+ .getOrElseThrow(() -> new InvalidCommandArgument("The destination " + destination + " is not valid."));
}
private GameRule> parseGameRule(BukkitCommandExecutionContext context) {
diff --git a/src/main/java/org/mvplugins/multiverse/core/api/Destination.java b/src/main/java/org/mvplugins/multiverse/core/destination/Destination.java
similarity index 80%
rename from src/main/java/org/mvplugins/multiverse/core/api/Destination.java
rename to src/main/java/org/mvplugins/multiverse/core/destination/Destination.java
index b5dd193c..6ee076d4 100644
--- a/src/main/java/org/mvplugins/multiverse/core/api/Destination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/Destination.java
@@ -1,4 +1,4 @@
-package org.mvplugins.multiverse.core.api;
+package org.mvplugins.multiverse.core.destination;
import java.util.Collection;
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Contract;
@Contract
-public interface Destination {
+public interface Destination, T extends DestinationInstance> {
/**
* Returns the identifier or prefix that is required for this destination.
*
@@ -36,13 +36,4 @@ public interface Destination {
* @return A list of possible destinations.
*/
@NotNull Collection suggestDestinations(@NotNull BukkitCommandIssuer issuer, @Nullable String destinationParams);
-
- /**
- * Should the Multiverse SafeTeleporter be used?
- *
- * If not, MV will blindly take people to the location specified.
- *
- * @return True if the SafeTeleporter will be used, false if not.
- */
- boolean checkTeleportSafety();
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/DestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/DestinationInstance.java
new file mode 100644
index 00000000..a5949f38
--- /dev/null
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/DestinationInstance.java
@@ -0,0 +1,90 @@
+package org.mvplugins.multiverse.core.destination;
+
+import io.vavr.control.Option;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class DestinationInstance, T extends Destination> {
+
+ protected final T destination;
+
+ protected DestinationInstance(@NotNull T destination) {
+ this.destination = destination;
+ }
+
+ /**
+ * Gets the destination that created this instance.
+ *
+ * @return The destination.
+ */
+ public @NotNull T getDestination() {
+ return this.destination;
+ }
+
+ /**
+ * Gets the {@link Destination#getIdentifier()} for this instance.
+ *
+ * @return The identifier.
+ */
+ public @NotNull String getIdentifier() {
+ return this.destination.getIdentifier();
+ }
+
+ /**
+ * Gets the exact location to teleport an entity to.
+ *
+ * @param teleportee The entity to teleport.
+ * @return The location to teleport to.
+ */
+ public abstract @NotNull Option getLocation(@NotNull Entity teleportee);
+
+ /**
+ * Gets the velocity to apply to an entity after teleporting.
+ *
+ * @param teleportee The entity to teleport.
+ * @return A vector representing the speed/direction the player should travel when arriving at the destination.
+ */
+ public abstract @NotNull Option getVelocity(@NotNull Entity teleportee);
+
+ /**
+ * Should the Multiverse SafeTeleporter be used?
+ *
+ * If not, MV will blindly take people to the location specified.
+ *
+ * @return True if the SafeTeleporter will be used, false if not.
+ */
+ public abstract boolean checkTeleportSafety();
+
+ /**
+ * Gets the permission suffix to check for when teleporting to this destination.
+ * This is used for finer per world/player permissions, such as "multiverse.teleport.self.worldname".
+ *
+ * For example, if the destination is "w:world", the permission suffix is "world".
+ *
+ * @return The permission suffix.
+ */
+ public abstract @NotNull Option getFinerPermissionSuffix();
+
+ /**
+ * Serialises the destination instance to a savable string.
+ *
+ * This is used when plugins save destinations to configuration,
+ * and when the destination is displayed to the user.
+ *
+ * @return The serialised destination instance.
+ */
+ @NotNull
+ protected abstract String serialise();
+
+ /**
+ * String representation of the destination instance that can be deserialised back into the destination instance.
+ * @return The string representation of the destination instance.
+ */
+ @Override
+ public String toString() {
+ return this.destination.getIdentifier() + ":" + this.serialise();
+ }
+}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/DestinationsProvider.java b/src/main/java/org/mvplugins/multiverse/core/destination/DestinationsProvider.java
index 50d75da3..2ad7ec44 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/DestinationsProvider.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/DestinationsProvider.java
@@ -6,6 +6,7 @@ import java.util.Map;
import java.util.stream.Collectors;
import co.aikar.commands.BukkitCommandIssuer;
+import io.vavr.control.Option;
import jakarta.inject.Inject;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
@@ -13,9 +14,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
-
/**
* Provides destinations for teleportation.
*/
@@ -25,7 +23,7 @@ public class DestinationsProvider {
private static final String PERMISSION_PREFIX = "multiverse.teleport.";
private final PluginManager pluginManager;
- private final Map> destinationMap;
+ private final Map> destinationMap;
@Inject
DestinationsProvider(@NotNull PluginManager pluginManager) {
@@ -38,12 +36,12 @@ public class DestinationsProvider {
*
* @param destination The destination.
*/
- public void registerDestination(@NotNull Destination> destination) {
+ public void registerDestination(@NotNull Destination, ?> destination) {
this.destinationMap.put(destination.getIdentifier(), destination);
this.registerDestinationPerms(destination);
}
- private void registerDestinationPerms(@NotNull Destination> destination) {
+ private void registerDestinationPerms(@NotNull Destination, ?> destination) {
pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "self." + destination.getIdentifier()));
pluginManager.addPermission(new Permission(PERMISSION_PREFIX + "other." + destination.getIdentifier()));
}
@@ -74,13 +72,13 @@ public class DestinationsProvider {
* @param destinationString The destination string.
* @return The destination object, or null if invalid format.
*/
- @Nullable
- public ParsedDestination> parseDestination(@NotNull String destinationString) {
+ @NotNull
+ public Option> parseDestination(@NotNull String destinationString) {
String[] items = destinationString.split(SEPARATOR, 2);
String idString = items[0];
String destinationParams;
- Destination> destination;
+ Destination, ?> destination;
if (items.length < 2) {
// Assume world destination
@@ -92,15 +90,10 @@ public class DestinationsProvider {
}
if (destination == null) {
- return null;
+ return Option.none();
}
- DestinationInstance destinationInstance = destination.getDestinationInstance(destinationParams);
- if (destinationInstance == null) {
- return null;
- }
-
- return new ParsedDestination<>(destination, destinationInstance);
+ return Option.of(destination.getDestinationInstance(destinationParams));
}
/**
@@ -109,7 +102,7 @@ public class DestinationsProvider {
* @param identifier The identifier.
* @return The destination, or null if not found.
*/
- public @Nullable Destination> getDestinationById(@Nullable String identifier) {
+ public @Nullable Destination, ?> getDestinationById(@Nullable String identifier) {
return this.destinationMap.get(identifier);
}
@@ -118,7 +111,7 @@ public class DestinationsProvider {
*
* @return A collection of destinations.
*/
- public @NotNull Collection> getDestinations() {
+ public @NotNull Collection> getDestinations() {
return this.destinationMap.values();
}
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/ParsedDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/ParsedDestination.java
deleted file mode 100644
index 5bf1894e..00000000
--- a/src/main/java/org/mvplugins/multiverse/core/destination/ParsedDestination.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.mvplugins.multiverse.core.destination;
-
-import org.bukkit.Location;
-import org.bukkit.entity.Entity;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import org.mvplugins.multiverse.core.api.Destination;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
-
-/**
- * A parsed destination.
- *
- * @param The destination instance type.
- */
-public class ParsedDestination {
- private final Destination destination;
- private final DestinationInstance destinationInstance;
-
- /**
- * Creates a new parsed destination.
- *
- * @param destination The destination.
- * @param destinationInstance The destination instance.
- */
- public ParsedDestination(Destination destination, DestinationInstance destinationInstance) {
- this.destination = destination;
- this.destinationInstance = destinationInstance;
- }
-
- /**
- * Shortcut for {@link Destination#getIdentifier()}.
- *
- * @return The destination identifier.
- */
- public @NotNull String getIdentifier() {
- return destination.getIdentifier();
- }
-
- /**
- * Shortcut for {@link DestinationInstance#getLocation(Entity)}.
- *
- * @param teleportee The entity to teleport.
- * @return The location to teleport to.
- */
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
- return destinationInstance.getLocation(teleportee);
- }
-
- /**
- * Shortcut for {@link DestinationInstance#getFinerPermissionSuffix()}.
- *
- * @return The finer permission suffix.
- */
- public @Nullable String getFinerPermissionSuffix() {
- return destinationInstance.getFinerPermissionSuffix();
- }
-
- /**
- * Gets the destination.
- *
- * @return The destination.
- */
- public Destination getDestination() {
- return destination;
- }
-
- /**
- * Gets the destination instance.
- *
- * @return The destination instance.
- */
- public DestinationInstance getDestinationInstance() {
- return destinationInstance;
- }
-
- /**
- * Converts to saveable string representation of this destination.
- *
- * @return Serialized string.
- */
- @Override
- public String toString() {
- return getIdentifier() + ":" + destinationInstance.serialise();
- }
-}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestination.java
index 88ded3ba..4793c470 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestination.java
@@ -10,13 +10,13 @@ import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.anchor.AnchorManager;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
/**
* {@link Destination} implementation for anchors.
*/
@Service
-public class AnchorDestination implements Destination {
+public class AnchorDestination implements Destination {
private final AnchorManager anchorManager;
@@ -38,11 +38,14 @@ public class AnchorDestination implements Destination
*/
@Override
public @Nullable AnchorDestinationInstance getDestinationInstance(@Nullable String destinationParams) {
+ if (destinationParams == null) {
+ return null;
+ }
Location anchorLocation = this.anchorManager.getAnchorLocation(destinationParams);
if (anchorLocation == null) {
return null;
}
- return new AnchorDestinationInstance(destinationParams, anchorLocation);
+ return new AnchorDestinationInstance(this, destinationParams, anchorLocation);
}
/**
@@ -52,12 +55,4 @@ public class AnchorDestination implements Destination
public @NotNull Collection suggestDestinations(@NotNull BukkitCommandIssuer issuer, @Nullable String destinationParams) {
return this.anchorManager.getAnchors(issuer.getPlayer());
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean checkTeleportSafety() {
- return true;
- }
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestinationInstance.java
index e96d6878..615a2868 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestinationInstance.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/AnchorDestinationInstance.java
@@ -1,17 +1,18 @@
package org.mvplugins.multiverse.core.destination.core;
+import io.vavr.control.Option;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
/**
* Destination instance implementation for the {@link AnchorDestination}.
*/
-public class AnchorDestinationInstance implements DestinationInstance {
+public class AnchorDestinationInstance extends DestinationInstance {
private final String anchorName;
private final Location anchorLocation;
@@ -21,7 +22,12 @@ public class AnchorDestinationInstance implements DestinationInstance {
* @param anchorName The name of the anchor.
* @param anchorLocation The location of the anchor.
*/
- AnchorDestinationInstance(@NotNull String anchorName, @NotNull Location anchorLocation) {
+ AnchorDestinationInstance(
+ @NotNull AnchorDestination destination,
+ @NotNull String anchorName,
+ @NotNull Location anchorLocation
+ ) {
+ super(destination);
this.anchorName = anchorName;
this.anchorLocation = anchorLocation;
}
@@ -30,24 +36,32 @@ public class AnchorDestinationInstance implements DestinationInstance {
* {@inheritDoc}
*/
@Override
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
- return anchorLocation;
+ public @NotNull Option getLocation(@NotNull Entity teleportee) {
+ return Option.of(anchorLocation);
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable Vector getVelocity(@NotNull Entity teleportee) {
- return null;
+ public @NotNull Option getVelocity(@NotNull Entity teleportee) {
+ return Option.none();
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable String getFinerPermissionSuffix() {
- return anchorName;
+ public boolean checkTeleportSafety() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Option getFinerPermissionSuffix() {
+ return Option.of(anchorName);
}
/**
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestination.java
index 2204703a..312c16a6 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestination.java
@@ -11,14 +11,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
import org.mvplugins.multiverse.core.utils.PlayerFinder;
/**
* {@link Destination} implementation for beds.
*/
@Service
-public class BedDestination implements Destination {
+public class BedDestination implements Destination {
static final String OWN_BED_STRING = "playerbed";
BedDestination() {
@@ -41,7 +41,7 @@ public class BedDestination implements Destination {
if (player == null && !destinationParams.equals(OWN_BED_STRING)) {
return null;
}
- return new BedDestinationInstance(player);
+ return new BedDestinationInstance(this, player);
}
/**
@@ -53,12 +53,4 @@ public class BedDestination implements Destination {
collect.add(OWN_BED_STRING);
return collect;
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean checkTeleportSafety() {
- return false;
- }
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestinationInstance.java
index d73c2ad6..3c3bb104 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestinationInstance.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/BedDestinationInstance.java
@@ -1,5 +1,6 @@
package org.mvplugins.multiverse.core.destination.core;
+import io.vavr.control.Option;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -7,12 +8,12 @@ import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
/**
* Destination instance implementation for the {@link BedDestination}.
*/
-public class BedDestinationInstance implements DestinationInstance {
+public class BedDestinationInstance extends DestinationInstance {
private final Player player;
/**
@@ -20,7 +21,8 @@ public class BedDestinationInstance implements DestinationInstance {
*
* @param player The player whose bed to use.
*/
- BedDestinationInstance(Player player) {
+ BedDestinationInstance(@NotNull BedDestination destination, @Nullable Player player) {
+ super(destination);
this.player = player;
}
@@ -28,30 +30,38 @@ public class BedDestinationInstance implements DestinationInstance {
* {@inheritDoc}
*/
@Override
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
+ public @NotNull Option getLocation(@NotNull Entity teleportee) {
if (player != null) {
- return player.getBedSpawnLocation();
+ return Option.of(player.getBedSpawnLocation());
}
if (teleportee instanceof Player) {
- return ((Player) teleportee).getBedSpawnLocation();
+ return Option.of(((Player) teleportee).getBedSpawnLocation());
}
- return null;
+ return Option.none();
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable Vector getVelocity(@NotNull Entity teleportee) {
- return null;
+ public @NotNull Option getVelocity(@NotNull Entity teleportee) {
+ return Option.none();
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable String getFinerPermissionSuffix() {
- return player != null ? player.getName() : BedDestination.OWN_BED_STRING;
+ public boolean checkTeleportSafety() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Option getFinerPermissionSuffix() {
+ return Option.of(player != null ? player.getName() : BedDestination.OWN_BED_STRING);
}
/**
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestination.java
index 84c7db23..4b6ce529 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestination.java
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
@@ -19,7 +19,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
* {@link Destination} implementation for cannons.
*/
@Service
-public class CannonDestination implements Destination {
+public class CannonDestination implements Destination {
private final WorldManager worldManager;
@@ -78,7 +78,7 @@ public class CannonDestination implements Destination
return null;
}
- return new CannonDestinationInstance(location, dSpeed);
+ return new CannonDestinationInstance(this, location, dSpeed);
}
/**
@@ -88,12 +88,4 @@ public class CannonDestination implements Destination
public @NotNull Collection suggestDestinations(@NotNull BukkitCommandIssuer issuer, @Nullable String destinationParams) {
return Collections.singleton("");
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean checkTeleportSafety() {
- return false;
- }
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestinationInstance.java
index 41205ac6..93e146b3 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestinationInstance.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/CannonDestinationInstance.java
@@ -1,17 +1,19 @@
package org.mvplugins.multiverse.core.destination.core;
+import io.vavr.control.Option;
import org.bukkit.Location;
+import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
/**
* Destination instance implementation for the {@link CannonDestination}.
*/
-public class CannonDestinationInstance implements DestinationInstance {
+public class CannonDestinationInstance extends DestinationInstance {
private final Location location;
private final double speed;
@@ -21,7 +23,8 @@ public class CannonDestinationInstance implements DestinationInstance {
* @param location The location to teleport to.
* @param speed The speed to fire the player at.
*/
- CannonDestinationInstance(@NotNull Location location, double speed) {
+ CannonDestinationInstance(@NotNull CannonDestination destination, @NotNull Location location, double speed) {
+ super(destination);
this.location = location;
this.speed = speed;
}
@@ -30,15 +33,15 @@ public class CannonDestinationInstance implements DestinationInstance {
* {@inheritDoc}
*/
@Override
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
- return location;
+ public @NotNull Option getLocation(@NotNull Entity teleportee) {
+ return Option.of(location);
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable Vector getVelocity(@NotNull Entity teleportee) {
+ public @NotNull Option getVelocity(@NotNull Entity teleportee) {
double pitchRadians = Math.toRadians(location.getPitch());
double yawRadians = Math.toRadians(location.getYaw());
double x = Math.sin(yawRadians) * speed * -1;
@@ -47,15 +50,23 @@ public class CannonDestinationInstance implements DestinationInstance {
// Account for the angle they were pointed, and take away velocity
x = Math.cos(pitchRadians) * x;
z = Math.cos(pitchRadians) * z;
- return new Vector(x, y, z);
+ return Option.of(new Vector(x, y, z));
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable String getFinerPermissionSuffix() {
- return location.getWorld().getName();
+ public boolean checkTeleportSafety() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Option getFinerPermissionSuffix() {
+ return Option.of(location.getWorld()).map(World::getName);
}
/**
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestination.java
index 0eaaf2b5..d62f3dfd 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestination.java
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
@@ -19,7 +19,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
* {@link Destination} implementation for exact locations.
*/
@Service
-public class ExactDestination implements Destination {
+public class ExactDestination implements Destination {
private final WorldManager worldManager;
@@ -36,6 +36,16 @@ public class ExactDestination implements Destination {
return "e";
}
+ /**
+ * Make a new {@link ExactDestinationInstance} from a {@link Location}.
+ *
+ * @param location The target location
+ * @return A new {@link ExactDestinationInstance}
+ */
+ public @NotNull ExactDestinationInstance fromLocation(@NotNull Location location) {
+ return new ExactDestinationInstance(this, location);
+ }
+
/**
* {@inheritDoc}
*/
@@ -53,7 +63,7 @@ public class ExactDestination implements Destination {
return null;
}
- World world = this.worldManager.getLoadedWorld(worldName).map(LoadedMultiverseWorld::getBukkitWorld).getOrNull().getOrNull();
+ World world = this.worldManager.getLoadedWorld(worldName).flatMap(LoadedMultiverseWorld::getBukkitWorld).getOrNull();
if (world == null) {
return null;
}
@@ -81,7 +91,7 @@ public class ExactDestination implements Destination {
}
}
- return new ExactDestinationInstance(location);
+ return new ExactDestinationInstance(this, location);
}
/**
@@ -91,12 +101,4 @@ public class ExactDestination implements Destination {
public @NotNull Collection suggestDestinations(@NotNull BukkitCommandIssuer issuer, @Nullable String destinationParams) {
return Collections.singleton("");
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean checkTeleportSafety() {
- return false;
- }
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestinationInstance.java
index 24882ded..d8561a43 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestinationInstance.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/ExactDestinationInstance.java
@@ -1,17 +1,19 @@
package org.mvplugins.multiverse.core.destination.core;
+import io.vavr.control.Option;
import org.bukkit.Location;
+import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
/**
* Destination instance implementation for the {@link ExactDestination}.
*/
-public class ExactDestinationInstance implements DestinationInstance {
+public class ExactDestinationInstance extends DestinationInstance {
private final Location location;
/**
@@ -19,7 +21,8 @@ public class ExactDestinationInstance implements DestinationInstance {
*
* @param location The location to teleport to.
*/
- ExactDestinationInstance(Location location) {
+ ExactDestinationInstance(@NotNull ExactDestination destination, @NotNull Location location) {
+ super(destination);
this.location = location;
}
@@ -27,24 +30,33 @@ public class ExactDestinationInstance implements DestinationInstance {
* {@inheritDoc}
*/
@Override
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
- return location;
+ public @NotNull Option getLocation(@NotNull Entity teleportee) {
+ // todo: maybe check if the world is null?
+ return Option.of(location);
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable Vector getVelocity(@NotNull Entity teleportee) {
- return null;
+ public @NotNull Option getVelocity(@NotNull Entity teleportee) {
+ return Option.none();
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable String getFinerPermissionSuffix() {
- return location.getWorld().getName();
+ public boolean checkTeleportSafety() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Option getFinerPermissionSuffix() {
+ return Option.of(location.getWorld()).map(World::getName);
}
/**
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestination.java
index 64253f8d..00d5a535 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestination.java
@@ -10,14 +10,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
import org.mvplugins.multiverse.core.utils.PlayerFinder;
/**
* {@link Destination} implementation for players.s
*/
@Service
-public class PlayerDestination implements Destination {
+public class PlayerDestination implements Destination {
/**
* Creates a new instance of the PlayerDestination.
*/
@@ -41,7 +41,7 @@ public class PlayerDestination implements Destination
if (player == null) {
return null;
}
- return new PlayerDestinationInstance(player);
+ return new PlayerDestinationInstance(this, player);
}
/**
@@ -49,14 +49,6 @@ public class PlayerDestination implements Destination
*/
@Override
public @NotNull Collection suggestDestinations(@NotNull BukkitCommandIssuer issuer, @Nullable String destinationParams) {
- return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean checkTeleportSafety() {
- return true;
+ return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();
}
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestinationInstance.java
index fd67f737..ecba3b8d 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestinationInstance.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/PlayerDestinationInstance.java
@@ -1,5 +1,6 @@
package org.mvplugins.multiverse.core.destination.core;
+import io.vavr.control.Option;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -7,12 +8,12 @@ import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
/**
* Destination instance implementation for the {@link PlayerDestination}.
*/
-public class PlayerDestinationInstance implements DestinationInstance {
+public class PlayerDestinationInstance extends DestinationInstance {
private final Player player;
/**
@@ -20,7 +21,8 @@ public class PlayerDestinationInstance implements DestinationInstance {
*
* @param player The player whose location to go to.
*/
- PlayerDestinationInstance(Player player) {
+ PlayerDestinationInstance(@NotNull PlayerDestination destination, @NotNull Player player) {
+ super(destination);
this.player = player;
}
@@ -28,24 +30,32 @@ public class PlayerDestinationInstance implements DestinationInstance {
* {@inheritDoc}
*/
@Override
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
- return player.getLocation();
+ public @NotNull Option getLocation(@NotNull Entity teleportee) {
+ return Option.of(player.getLocation());
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable Vector getVelocity(@NotNull Entity teleportee) {
- return null;
+ public @NotNull Option getVelocity(@NotNull Entity teleportee) {
+ return Option.none();
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable String getFinerPermissionSuffix() {
- return player.getName();
+ public boolean checkTeleportSafety() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Option getFinerPermissionSuffix() {
+ return Option.of(player.getName());
}
/**
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestination.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestination.java
index b28aec4c..bf85af04 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestination.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestination.java
@@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
import org.mvplugins.multiverse.core.api.LocationManipulation;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
@@ -18,7 +18,7 @@ import org.mvplugins.multiverse.core.world.WorldManager;
* {@link Destination} implementation for exact locations.
*/
@Service
-public class WorldDestination implements Destination {
+public class WorldDestination implements Destination {
private final WorldManager worldManager;
private final LocationManipulation locationManipulation;
@@ -56,7 +56,7 @@ public class WorldDestination implements Destination {
String direction = (items.length == 2) ? items[1] : null;
float yaw = direction != null ? this.locationManipulation.getYaw(direction) : -1;
- return new WorldDestinationInstance(world, direction, yaw);
+ return new WorldDestinationInstance(this, world, direction, yaw);
}
/**
@@ -67,12 +67,4 @@ public class WorldDestination implements Destination {
// Autocomplete of worlds is done by MVCommandCompletion without prefix
return Collections.emptyList();
}
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean checkTeleportSafety() {
- return true;
- }
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestinationInstance.java b/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestinationInstance.java
index f0ce05fe..3f09d718 100644
--- a/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestinationInstance.java
+++ b/src/main/java/org/mvplugins/multiverse/core/destination/core/WorldDestinationInstance.java
@@ -1,18 +1,19 @@
package org.mvplugins.multiverse.core.destination.core;
+import io.vavr.control.Option;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.mvplugins.multiverse.core.api.DestinationInstance;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
/**
* Destination instance implementation for the {@link WorldDestination}.
*/
-public class WorldDestinationInstance implements DestinationInstance {
+public class WorldDestinationInstance extends DestinationInstance {
private final LoadedMultiverseWorld world;
private final String direction;
private final float yaw;
@@ -20,11 +21,18 @@ public class WorldDestinationInstance implements DestinationInstance {
/**
* Constructor.
*
- * @param world The world to teleport to.
- * @param direction The direction to face.
- * @param yaw The yaw to face.
+ * @param destination The destination.
+ * @param world The world to teleport to.
+ * @param direction The direction to face.
+ * @param yaw The yaw to face.
*/
- WorldDestinationInstance(@NotNull LoadedMultiverseWorld world, @Nullable String direction, float yaw) {
+ WorldDestinationInstance(
+ @NotNull WorldDestination destination,
+ @NotNull LoadedMultiverseWorld world,
+ @Nullable String direction,
+ float yaw
+ ) {
+ super(destination);
this.world = world;
this.direction = direction;
this.yaw = yaw;
@@ -34,29 +42,37 @@ public class WorldDestinationInstance implements DestinationInstance {
* {@inheritDoc}
*/
@Override
- public @Nullable Location getLocation(@NotNull Entity teleportee) {
+ public @NotNull Option getLocation(@NotNull Entity teleportee) {
Location worldLoc = world.getSpawnLocation();
if (this.yaw >= 0) {
// Only modify the yaw if its set.
worldLoc.setYaw(this.yaw);
}
- return worldLoc;
+ return Option.of(worldLoc);
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable Vector getVelocity(@NotNull Entity teleportee) {
- return null;
+ public @NotNull Option getVelocity(@NotNull Entity teleportee) {
+ return Option.none();
}
/**
* {@inheritDoc}
*/
@Override
- public @Nullable String getFinerPermissionSuffix() {
- return world.getName();
+ public boolean checkTeleportSafety() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NotNull Option getFinerPermissionSuffix() {
+ return Option.of(world.getName());
}
/**
diff --git a/src/main/java/org/mvplugins/multiverse/core/event/MVTeleportEvent.java b/src/main/java/org/mvplugins/multiverse/core/event/MVTeleportEvent.java
index 532213b3..196ddb59 100644
--- a/src/main/java/org/mvplugins/multiverse/core/event/MVTeleportEvent.java
+++ b/src/main/java/org/mvplugins/multiverse/core/event/MVTeleportEvent.java
@@ -14,7 +14,7 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
/**
@@ -23,11 +23,11 @@ import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
public class MVTeleportEvent extends Event implements Cancellable {
private Player teleportee;
private CommandSender teleporter;
- private ParsedDestination> dest;
+ private DestinationInstance, ?> dest;
private boolean useSafeTeleport;
private boolean isCancelled;
- public MVTeleportEvent(ParsedDestination> dest, Player teleportee, CommandSender teleporter, boolean safeTeleport) {
+ public MVTeleportEvent(DestinationInstance, ?> dest, Player teleportee, CommandSender teleporter, boolean safeTeleport) {
this.teleportee = teleportee;
this.teleporter = teleporter;
this.dest = dest;
@@ -84,7 +84,7 @@ public class MVTeleportEvent extends Event implements Cancellable {
*
* @return The destination the player will spawn at.
*/
- public ParsedDestination> getDestination() {
+ public DestinationInstance, ?> getDestination() {
return this.dest;
}
diff --git a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java
index dca3ef50..07334465 100644
--- a/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java
+++ b/src/main/java/org/mvplugins/multiverse/core/listeners/MVPlayerListener.java
@@ -36,8 +36,8 @@ import org.mvplugins.multiverse.core.MultiverseCore;
import org.mvplugins.multiverse.core.api.BlockSafety;
import org.mvplugins.multiverse.core.commandtools.MVCommandManager;
import org.mvplugins.multiverse.core.config.MVCoreConfig;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.economy.MVEconomist;
import org.mvplugins.multiverse.core.event.MVRespawnEvent;
import org.mvplugins.multiverse.core.teleportation.AsyncSafetyTeleporter;
@@ -173,7 +173,8 @@ public class MVPlayerListener implements CoreListener {
return;
}
- Option.of(destinationsProvider.parseDestination(config.getFirstSpawnLocation()))
+ // todo: Config should auto serialise to and from DestinationInstance
+ destinationsProvider.parseDestination(config.getFirstSpawnLocation())
.peek(parsedDestination -> {
if (!player.hasPlayedBefore()) {
Logging.finer("Player joined for the FIRST time!");
@@ -207,15 +208,9 @@ public class MVPlayerListener implements CoreListener {
}
Logging.finer("JoinDestination is " + config.getJoinDestination());
- ParsedDestination> joinDestination = destinationsProvider.parseDestination(config.getJoinDestination());
-
- if (joinDestination == null) {
- Logging.warning("The destination in JoinDestination in config is invalid");
- return;
- }
-
- // Finally, teleport the player
- safetyTeleporter.teleportSafely(player, player, joinDestination);
+ destinationsProvider.parseDestination(config.getJoinDestination())
+ .peek(destination -> safetyTeleporter.teleportSafely(player, player, destination))
+ .onEmpty(() -> Logging.warning("The destination in JoinDestination in config is invalid"));
}
/**
@@ -350,7 +345,7 @@ public class MVPlayerListener implements CoreListener {
Logging.fine("Teleport result: %s", entryResult);
}
- private void sendPlayerToDefaultWorld(final Player player, ParsedDestination parsedDestination) {
+ private void sendPlayerToDefaultWorld(final Player player, DestinationInstance, ?> parsedDestination) {
// Remove the player 1 tick after the login. I'm sure there's GOT to be a better way to do this...
this.server.getScheduler().scheduleSyncDelayedTask(this.plugin,
new Runnable() {
diff --git a/src/main/java/org/mvplugins/multiverse/core/permissions/CorePermissionsChecker.java b/src/main/java/org/mvplugins/multiverse/core/permissions/CorePermissionsChecker.java
index 9e934535..9fea9c46 100644
--- a/src/main/java/org/mvplugins/multiverse/core/permissions/CorePermissionsChecker.java
+++ b/src/main/java/org/mvplugins/multiverse/core/permissions/CorePermissionsChecker.java
@@ -7,16 +7,16 @@ import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
import org.jvnet.hk2.annotations.Service;
-import org.mvplugins.multiverse.core.api.Destination;
+import org.mvplugins.multiverse.core.destination.Destination;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.MultiverseWorld;
@Service
public class CorePermissionsChecker {
- private DestinationsProvider destinationsProvider;
+ private final DestinationsProvider destinationsProvider;
@Inject
CorePermissionsChecker(@NotNull DestinationsProvider destinationsProvider) {
@@ -50,7 +50,7 @@ public class CorePermissionsChecker {
public boolean checkTeleportPermissions(
@NotNull CommandSender teleporter,
@NotNull Entity teleportee,
- @NotNull ParsedDestination> destination) {
+ @NotNull DestinationInstance, ?> destination) {
String permission = concatPermission(
CorePermissions.TELEPORT,
@@ -61,13 +61,13 @@ public class CorePermissionsChecker {
}
// TODO: Config whether to use finer permission
- String finerPermissionSuffix = destination.getDestinationInstance().getFinerPermissionSuffix();
- if (finerPermissionSuffix == null || finerPermissionSuffix.isEmpty()) {
- return true;
- }
-
- String finerPermission = concatPermission(permission, finerPermissionSuffix);
- return hasPermission(teleporter, finerPermission);
+ return destination.getFinerPermissionSuffix()
+ .filter(String::isBlank)
+ .map(finerPermissionSuffix -> hasPermission(
+ teleporter,
+ concatPermission(permission, finerPermissionSuffix)
+ ))
+ .getOrElse(true);
}
/**
@@ -77,7 +77,7 @@ public class CorePermissionsChecker {
* @return True if the issuer has permission, false otherwise.
*/
public boolean hasAnyTeleportPermission(CommandSender sender) {
- for (Destination> destination : destinationsProvider.getDestinations()) {
+ for (Destination, ?> destination : destinationsProvider.getDestinations()) {
String permission = concatPermission(CorePermissions.TELEPORT, "self", destination.getIdentifier());
if (hasPermission(sender, permission)) {
return true;
diff --git a/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporter.java b/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporter.java
index 4ee84d1a..9c9de783 100644
--- a/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporter.java
+++ b/src/main/java/org/mvplugins/multiverse/core/teleportation/AsyncSafetyTeleporter.java
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
import org.mvplugins.multiverse.core.api.BlockSafety;
-import org.mvplugins.multiverse.core.destination.ParsedDestination;
+import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.utils.result.Async;
import org.mvplugins.multiverse.core.utils.result.AsyncAttempt;
import org.mvplugins.multiverse.core.utils.result.Attempt;
@@ -37,14 +37,14 @@ public class AsyncSafetyTeleporter {
public AsyncAttempt teleportSafely(
@NotNull Entity teleportee,
- @Nullable ParsedDestination> destination) {
+ @Nullable DestinationInstance, ?> destination) {
return teleportSafely(null, teleportee, destination);
}
public Async>> teleportSafely(
@Nullable CommandSender teleporter,
@NotNull List teleportees,
- @Nullable ParsedDestination> destination) {
+ @Nullable DestinationInstance, ?> destination) {
return AsyncAttempt.allOf(teleportees.stream()
.map(teleportee -> teleportSafely(teleporter, teleportee, destination))
.toList());
@@ -53,13 +53,15 @@ public class AsyncSafetyTeleporter {
public AsyncAttempt teleportSafely(
@Nullable CommandSender teleporter,
@NotNull Entity teleportee,
- @Nullable ParsedDestination> destination) {
+ @Nullable DestinationInstance, ?> destination) {
if (destination == null) {
return AsyncAttempt.failure(TeleportResult.Failure.NULL_DESTINATION);
}
- return destination.getDestination().checkTeleportSafety()
- ? teleportSafely(teleporter, teleportee, destination.getLocation(teleportee))
- : teleport(teleporter, teleportee, destination.getLocation(teleportee));
+ return destination.getLocation(teleportee)
+ .map(location -> destination.checkTeleportSafety()
+ ? teleportSafely(teleporter, teleportee, location)
+ : teleport(teleporter, teleportee, location))
+ .getOrElse(AsyncAttempt.failure(TeleportResult.Failure.NULL_LOCATION));
}
public AsyncAttempt teleportSafely(
@@ -84,7 +86,7 @@ public class AsyncSafetyTeleporter {
public Async>> teleport(
@NotNull List teleportees,
- @Nullable ParsedDestination> destination) {
+ @Nullable DestinationInstance, ?> destination) {
return AsyncAttempt.allOf(teleportees.stream()
.map(teleportee -> teleport(teleportee, destination))
.toList());
@@ -92,18 +94,20 @@ public class AsyncSafetyTeleporter {
public AsyncAttempt teleport(
@NotNull Entity teleportee,
- @Nullable ParsedDestination> destination) {
+ @Nullable DestinationInstance, ?> destination) {
return teleport(null, teleportee, destination);
}
public AsyncAttempt teleport(
@Nullable CommandSender teleporter,
@NotNull Entity teleportee,
- @Nullable ParsedDestination> destination) {
- if (destination == null) {
- return AsyncAttempt.failure(TeleportResult.Failure.NULL_DESTINATION);
- }
- return teleport(teleporter, teleportee, destination.getLocation(teleportee));
+ @Nullable DestinationInstance, ?> destination) {
+ if (destination == null) {
+ return AsyncAttempt.failure(TeleportResult.Failure.NULL_DESTINATION);
+ }
+ return destination.getLocation(teleportee)
+ .map(location -> teleport(teleporter, teleportee, location))
+ .getOrElse(AsyncAttempt.failure(TeleportResult.Failure.NULL_LOCATION));
}
public Async>> teleport(
@@ -139,15 +143,15 @@ public class AsyncSafetyTeleporter {
private AsyncAttempt doAsyncTeleport(
@NotNull Entity teleportee,
@NotNull Location location,
- boolean shouldAddToQueue) {
+ boolean shouldRemoveFromQueue) {
return AsyncAttempt.of(PaperLib.teleportAsync(teleportee, location), exception -> {
Logging.warning("Failed to teleport %s to %s: %s",
teleportee.getName(), location, exception.getMessage());
return Attempt.failure(TeleportResult.Failure.TELEPORT_FAILED_EXCEPTION);
- }).mapAttempt(result -> {
+ }).mapAttempt(success -> {
Logging.finer("Teleported async %s to %s", teleportee.getName(), location);
- if (result) {
- if (shouldAddToQueue) {
+ if (success) {
+ if (shouldRemoveFromQueue) {
teleportQueue.popFromQueue(teleportee.getName());
}
return Attempt.success(null);
diff --git a/src/test/java/org/mvplugins/multiverse/core/destination/DestinationTest.kt b/src/test/java/org/mvplugins/multiverse/core/destination/DestinationTest.kt
new file mode 100644
index 00000000..b260ab04
--- /dev/null
+++ b/src/test/java/org/mvplugins/multiverse/core/destination/DestinationTest.kt
@@ -0,0 +1,122 @@
+package org.mvplugins.multiverse.core.destination
+
+import org.bukkit.Location
+import org.mockbukkit.mockbukkit.entity.PlayerMock
+import org.mvplugins.multiverse.core.TestWithMockBukkit
+import org.mvplugins.multiverse.core.destination.core.*
+import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld
+import org.mvplugins.multiverse.core.world.WorldManager
+import org.mvplugins.multiverse.core.world.options.CreateWorldOptions
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class DestinationTest : TestWithMockBukkit() {
+
+ private lateinit var worldManager: WorldManager
+ private lateinit var destinationsProvider: DestinationsProvider
+ private lateinit var world: LoadedMultiverseWorld
+ private lateinit var player: PlayerMock
+
+ @BeforeTest
+ fun setUp() {
+ worldManager = serviceLocator.getActiveService(WorldManager::class.java).takeIf { it != null } ?: run {
+ throw IllegalStateException("WorldManager is not available as a service") }
+ destinationsProvider = serviceLocator.getActiveService(DestinationsProvider::class.java).takeIf { it != null } ?: run {
+ throw IllegalStateException("DestinationsProvider is not available as a service") }
+
+ world = worldManager.createWorld(CreateWorldOptions.worldName("world")).get()
+ player = server.addPlayer("benji_0224")
+ player.bedSpawnLocation = Location(world.bukkitWorld.orNull, 5.0, 10.0, 5.0)
+ }
+
+ @Test
+ fun `Bed destination instance`() {
+ assertTrue(destinationsProvider.getDestinationById("b") is BedDestination)
+ val destination = destinationsProvider.parseDestination("b:benji_0224").orNull
+ assertTrue(destination is BedDestinationInstance)
+ assertEquals(player.bedSpawnLocation, destination.getLocation(player).orNull)
+ assertEquals("b:benji_0224", destination.toString())
+ }
+
+ @Test
+ fun `Bed destination instance own player`() {
+ val destination = destinationsProvider.parseDestination("b:playerbed").orNull
+ assertTrue(destination is BedDestinationInstance)
+ assertEquals(player.bedSpawnLocation, destination.getLocation(player).orNull)
+ assertEquals("b:playerbed", destination.toString())
+ }
+
+ @Test
+ fun `Cannon destination instance`() {
+ assertTrue(destinationsProvider.getDestinationById("ca") is CannonDestination)
+ val destination = destinationsProvider.parseDestination("ca:world:1.2,2,3:10.5:9.5:5").orNull
+ assertTrue(destination is CannonDestinationInstance)
+ val expectedLocation = Location(world.bukkitWorld.orNull, 1.2, 2.0, 3.0, 9.5F, 10.5F)
+ assertEquals(expectedLocation, destination.getLocation(player).orNull)
+ // todo: assert the Vector
+ assertEquals("ca:world:1.2,2.0,3.0:10.5:9.5:5.0", destination.toString())
+ }
+
+ @Test
+ fun `Exact destination instance`() {
+ assertTrue(destinationsProvider.getDestinationById("e") is ExactDestination)
+ val destination = destinationsProvider.parseDestination("e:world:1.2,2,3:10.5:9.5").orNull
+ assertTrue(destination is ExactDestinationInstance)
+ val expectedLocation = Location(world.bukkitWorld.orNull, 1.2, 2.0, 3.0, 9.5F, 10.5F)
+ assertEquals(expectedLocation, destination.getLocation(player).orNull)
+ assertEquals("e:world:1.2,2.0,3.0:10.5:9.5", destination.toString())
+ }
+
+ @Test
+ fun `Exact destination instance from location`() {
+ val exactDestination = serviceLocator.getActiveService(ExactDestination::class.java).takeIf { it != null } ?: run {
+ throw IllegalStateException("ExactDestination is not available as a service") }
+
+ val location = Location(world.bukkitWorld.orNull, 1.2, 2.0, 3.0, 9.5F, 10.5F)
+ val destination = exactDestination.fromLocation(location)
+ assertEquals(location, destination.getLocation(player).orNull)
+ assertEquals("e:world:1.2,2.0,3.0:10.5:9.5", destination.toString())
+ }
+
+ @Test
+ fun `Player destination instance`() {
+ assertTrue(destinationsProvider.getDestinationById("pl") is PlayerDestination)
+ val destination = destinationsProvider.parseDestination("pl:benji_0224").orNull
+ assertTrue(destination is PlayerDestinationInstance)
+ assertEquals(player.location, destination.getLocation(player).orNull)
+ assertEquals("pl:benji_0224", destination.toString())
+ }
+
+ @Test
+ fun `World destination instance`() {
+ assertTrue(destinationsProvider.getDestinationById("w") is WorldDestination)
+ val destination = destinationsProvider.parseDestination("w:world").orNull
+ assertTrue(destination is WorldDestinationInstance)
+ assertEquals(world.spawnLocation, destination.getLocation(player).orNull)
+ assertEquals("w:world", destination.toString())
+ }
+
+ @Test
+ fun `World destination instance without identifier`() {
+ val destination = destinationsProvider.parseDestination("world").orNull
+ assertTrue(destination is WorldDestinationInstance)
+ assertEquals(world.spawnLocation, destination.getLocation(player).orNull)
+ assertEquals("w:world", destination.toString())
+ }
+
+ @Test
+ fun `Invalid destination instance`() {
+ assertTrue(destinationsProvider.parseDestination("").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("idk:world").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("a:invalid-anchor").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("b:invalid-bed").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("ca:invalid-cannon").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("e:world:1,2,x").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("pl:invalid-player").isEmpty)
+ assertTrue(destinationsProvider.parseDestination("w:invalid-world").isEmpty)
+ // todo: should we make invalid yaw for WorldDestination fail?
+ // assertTrue(destinationsProvider.parseDestination("w:world:f").isEmpty)
+ }
+}
diff --git a/src/test/java/org/mvplugins/multiverse/core/inject/InjectionTest.kt b/src/test/java/org/mvplugins/multiverse/core/inject/InjectionTest.kt
index 15c00dce..1dc0de8d 100644
--- a/src/test/java/org/mvplugins/multiverse/core/inject/InjectionTest.kt
+++ b/src/test/java/org/mvplugins/multiverse/core/inject/InjectionTest.kt
@@ -3,7 +3,7 @@ package org.mvplugins.multiverse.core.inject
import org.mvplugins.multiverse.core.TestWithMockBukkit
import org.mvplugins.multiverse.core.anchor.AnchorManager
import org.mvplugins.multiverse.core.api.BlockSafety
-import org.mvplugins.multiverse.core.api.Destination
+import org.mvplugins.multiverse.core.destination.Destination
import org.mvplugins.multiverse.core.api.LocationManipulation
import org.mvplugins.multiverse.core.commandtools.MVCommandManager
import org.mvplugins.multiverse.core.commandtools.MultiverseCommand
@@ -17,7 +17,6 @@ import org.mvplugins.multiverse.core.teleportation.SimpleLocationManipulation
import org.mvplugins.multiverse.core.teleportation.TeleportQueue
import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator
import org.mvplugins.multiverse.core.world.WorldManager
-import org.mvplugins.multiverse.core.world.config.WorldsConfigManager
import kotlin.test.*
class InjectionTest : TestWithMockBukkit() {
@@ -110,7 +109,6 @@ class InjectionTest : TestWithMockBukkit() {
@Test
fun `Destinations are available as services`() {
val destinations = serviceLocator.getAllActiveServices(Destination::class.java)
- // TODO: come up with a better way to test this like via actually testing the effect of using each destination
assertEquals(6, destinations.size)
}