Skip to content
Merged

V5.2 #699

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ repositories {
name = 'benthecat'
url = uri('https://repo.c0ding.party/multiverse-beta')
}
maven {
name = "helpchatRepoReleases"
url = uri("https://repo.helpch.at/releases/")
}
}

configure(apiDependencies) {
Expand All @@ -32,6 +36,9 @@ dependencies {
exclude group: 'org.bukkit', module: 'bukkit'
}

// PlaceholderAPI
externalPlugin 'me.clip:placeholderapi:2.11.6'

// Utils
shadowed('com.dumptruckman.minecraft:Logging:1.1.1') {
exclude group: 'junit', module: 'junit'
Expand Down
160 changes: 139 additions & 21 deletions src/main/java/org/mvplugins/multiverse/portals/MVPortal.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,23 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Pattern;

import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mvplugins.multiverse.core.command.MVCommandManager;
import org.mvplugins.multiverse.core.config.handle.MemoryConfigurationHandle;
import org.mvplugins.multiverse.core.config.handle.StringPropertyHandle;
import org.mvplugins.multiverse.core.config.migration.ConfigMigrator;
Expand All @@ -27,9 +34,16 @@
import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.teleportation.BlockSafety;
import org.mvplugins.multiverse.core.utils.result.Attempt;
import org.mvplugins.multiverse.core.utils.text.ChatTextFormatter;
import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld;
import org.mvplugins.multiverse.core.world.WorldManager;
import org.mvplugins.multiverse.external.vavr.control.Option;
import org.mvplugins.multiverse.external.vavr.control.Try;
import org.mvplugins.multiverse.portals.action.ActionFailureReason;
import org.mvplugins.multiverse.portals.action.ActionHandler;
import org.mvplugins.multiverse.portals.action.ActionHandlerProvider;
import org.mvplugins.multiverse.portals.action.ActionHandlerType;
import org.mvplugins.multiverse.portals.config.PortalsConfig;
import org.mvplugins.multiverse.portals.enums.PortalType;
import org.bukkit.Location;
Expand Down Expand Up @@ -62,6 +76,8 @@ public static MVPortal loadMVPortalFromConfig(MultiversePortals instance, String
private final WorldManager worldManager;
private final DestinationsProvider destinationsProvider;
private final BlockSafety blockSafety;
private final ActionHandlerProvider actionHandlerProvider;
private final MVCommandManager commandManager;

private final String name;
private final MVPortalNodes configNodes;
Expand Down Expand Up @@ -94,16 +110,24 @@ private MVPortal(MultiversePortals plugin, String name) {
this.worldManager = this.plugin.getServiceLocator().getService(WorldManager.class);
this.destinationsProvider = this.plugin.getServiceLocator().getService(DestinationsProvider.class);
this.blockSafety = this.plugin.getServiceLocator().getService(BlockSafety.class);
this.actionHandlerProvider = this.plugin.getServiceLocator().getService(ActionHandlerProvider.class);
this.commandManager = this.plugin.getServiceLocator().getService(MVCommandManager.class);

this.name = name;

var config = this.plugin.getPortalsConfig();
this.configNodes = new MVPortalNodes(plugin, this);
var portalSection = config.getConfigurationSection("portals." + this.name);
if (portalSection == null) {
portalSection = config.createSection("portals." + this.name);
}
this.configHandle = MemoryConfigurationHandle.builder(portalSection, configNodes.getNodes())
var portalSection = Option.of(config.getConfigurationSection("portals." + this.name))
.getOrElse(() -> config.createSection("portals." + this.name));
this.configHandle = setUpConfigHandle(portalSection);
this.stringPropertyHandle = new StringPropertyHandle(this.configHandle);
configHandle.load();

setUpPermissions();
}

private MemoryConfigurationHandle setUpConfigHandle(ConfigurationSection portalSection) {
return MemoryConfigurationHandle.builder(portalSection, configNodes.getNodes())
.migrator(ConfigMigrator.builder(configNodes.version)
.addVersionMigrator(VersionMigrator.builder(1.0)
.addAction(MoveMigratorAction.of("safeteleport", "safe-teleport"))
Expand All @@ -119,11 +143,14 @@ private MVPortal(MultiversePortals plugin, String name) {
}
})
.build())
.addVersionMigrator(VersionMigrator.builder(1.2)
.addAction(MoveMigratorAction.of("destination", "action"))
.build())
.build())
.build();
this.stringPropertyHandle = new StringPropertyHandle(this.configHandle);
configHandle.load();
}

private void setUpPermissions() {
this.permission = this.plugin.getServer().getPluginManager().getPermission("multiverse.portal.access." + this.name);
if (this.permission == null) {
this.permission = new Permission("multiverse.portal.access." + this.name, "Allows access to the " + this.name + " portal", PermissionDefault.OP);
Expand All @@ -142,6 +169,10 @@ private MVPortal(MultiversePortals plugin, String name) {
}
}

/**
*
* @return
*/
public String getName() {
return this.name;
}
Expand Down Expand Up @@ -271,24 +302,61 @@ public PortalLocation getPortalLocation() {
return this.location;
}

public boolean setDestination(String destinationString) {
DestinationInstance<?, ?> newDestination = this.destinationsProvider.parseDestination(destinationString).getOrNull();
return setDestination(newDestination);
@ApiStatus.AvailableSince("5.2")
public Try<Void> setActionType(@NotNull ActionHandlerType<?, ?> actionType) {
Objects.requireNonNull(actionType, "actionType cannot be null");
return configHandle.set(configNodes.actionType, actionType.getName());
}

public boolean setDestination(DestinationInstance<?, ?> newDestination) {
if (newDestination == null) {
Logging.warning("Portal " + this.name + " has an invalid DESTINATION!");
return false;
}
return this.configHandle.set(configNodes.destination, newDestination.toString()).isSuccess();
@ApiStatus.AvailableSince("5.2")
public Try<Void> setActionType(String actionType) {
return configHandle.set(configNodes.actionType, actionType);
}

public DestinationInstance<?, ?> getDestination() {
return this.destinationsProvider.parseDestination(this.configHandle.get(configNodes.destination))
.onFailure(f ->
Logging.warning("Portal " + this.name + " has an invalid DESTINATION! " + f.getFailureMessage().formatted()))
.getOrNull();
@ApiStatus.AvailableSince("5.2")
public String getActionType() {
return this.configHandle.get(configNodes.actionType);
}

@ApiStatus.AvailableSince("5.2")
public Try<Void> setAction(String action) {
return configHandle.set(configNodes.action, action);
}

@ApiStatus.AvailableSince("5.2")
public String getAction() {
return configHandle.get(configNodes.action);
}

@ApiStatus.AvailableSince("5.2")
public Try<Void> setActionHandler(@NotNull ActionHandler<?, ?> action) {
Objects.requireNonNull(action, "action cannot be null");
return setActionType(action.getHandlerType())
.flatMap(v -> setAction(action.serialise()));
}

@ApiStatus.AvailableSince("5.2")
public @NotNull Attempt<? extends ActionHandler<?, ?>, ActionFailureReason> getActionHandler() {
return actionHandlerProvider.parseHandler(getActionType(), getAction());
}

@ApiStatus.AvailableSince("5.2")
public @NotNull Attempt<? extends ActionHandler<?, ?>, ActionFailureReason> getActionHandler(@NotNull CommandSender sender) {
return actionHandlerProvider.parseHandler(sender, getActionType(), getAction());
}

@ApiStatus.AvailableSince("5.2")
public @NotNull Attempt<Void, ActionFailureReason> runActionFor(Entity entity) {
return getActionHandler(entity)
.mapAttempt(actionHandler -> actionHandler.runAction(this, entity))
.onSuccess(() -> {
if (entity instanceof Player player) {
plugin.getPortalSession(player).setTeleportTime(new Date());
}
})
.onFailure(failure ->
Logging.warning(ChatTextFormatter.removeColor("Invalid Portal Action: " +
failure.getFailureMessage().formatted(commandManager.getCommandIssuer(Bukkit.getConsoleSender())))));
}

/**
Expand Down Expand Up @@ -598,4 +666,54 @@ public boolean isExempt(Player player) {
public PortalLocation getLocation() {
return getPortalLocation();
}

/**
* @deprecated Portals now have new types of action. Hence, the portal's destination (now called action) may not
* always be a multiverse destination. It can be a command or server name as well.
* Please see {@link MVPortal#getActionHandler()} instead.
*/
@Deprecated(since = "5.2", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.0")
public boolean setDestination(String destinationString) {
DestinationInstance<?, ?> newDestination = this.destinationsProvider.parseDestination(destinationString).getOrNull();
return setDestination(newDestination);
}

/**
* @deprecated Portals now have new types of action. Hence, the portal's destination (now called action) may not
* always be a multiverse destination. For example, it can be a command or server name as well.
* Please see {@link MVPortal#getActionHandler()} instead.
*/
@Deprecated(since = "5.2", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.0")
public boolean setDestination(DestinationInstance<?, ?> newDestination) {
if (newDestination == null) {
Logging.warning("Portal " + this.name + " has an invalid DESTINATION!");
return false;
}
if (!Objects.equals(getActionType(), "multiverse-destination")) {
Logging.warning("Portal " + this.name + " is not set to use multiverse destination!");
return false;
}
return setActionType("multiverse-destination")
.flatMap(ignore -> setAction(newDestination.toString()))
.isSuccess();
}

/**
* @deprecated Portals now have new types of action. Hence, the portal's destination (now called action) may not
* always be a multiverse destination. For example, it can be a command or server name as well.
* Please see {@link MVPortal#getActionHandler()} instead.
*/
@Deprecated(since = "5.2", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.0")
public @Nullable DestinationInstance<?, ?> getDestination() {
return this.destinationsProvider.parseDestination(getAction())
.onFailure(f -> {
if (getAction().equals("multiverse-destination")) {
Logging.warning("Portal " + this.name + " has an invalid DESTINATION! " + f.getFailureMessage().formatted());
}
})
.getOrNull();
}
}
29 changes: 20 additions & 9 deletions src/main/java/org/mvplugins/multiverse/portals/MVPortalNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
import org.mvplugins.multiverse.core.config.node.ConfigNode;
import org.mvplugins.multiverse.core.config.node.Node;
import org.mvplugins.multiverse.core.config.node.NodeGroup;
import org.mvplugins.multiverse.core.destination.DestinationInstance;
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.exceptions.MultiverseException;
import org.mvplugins.multiverse.external.vavr.control.Try;
import org.mvplugins.multiverse.portals.action.ActionHandler;
import org.mvplugins.multiverse.portals.action.ActionHandlerProvider;
import org.mvplugins.multiverse.portals.utils.MultiverseRegion;

import java.util.Collections;
Expand All @@ -21,12 +22,12 @@ final class MVPortalNodes {

private MultiversePortals plugin;
private MVPortal portal;
private DestinationsProvider destinationsProvider;
private ActionHandlerProvider actionHandlerProvider;

MVPortalNodes(MultiversePortals plugin, MVPortal portal) {
this.plugin = plugin;
this.portal = portal;
this.destinationsProvider = MultiverseCoreApi.get().getDestinationsProvider();
this.actionHandlerProvider = plugin.getServiceLocator().getService(ActionHandlerProvider.class);
}

NodeGroup getNodes() {
Expand Down Expand Up @@ -90,13 +91,23 @@ private <N extends Node> N node(N node) {
.onSetValue((oldValue, newValue) -> portal.setPortalLocationInternal(PortalLocation.parseLocation(newValue)))
.build());

final ConfigNode<String> destination = node(ConfigNode.builder("destination", String.class)
final ConfigNode<String> actionType = node(ConfigNode.builder("action-type", String.class)
.suggester(input -> actionHandlerProvider.getAllHandlerTypeNames())
.defaultValue("multiverse-destination")
.build());

final ConfigNode<String> action = node(ConfigNode.builder("action", String.class)
.defaultValue("")
.aliases("dest")
.suggester((sender, input) -> destinationsProvider.suggestDestinationStrings(sender, input))
.stringParser((sender, input, type) -> destinationsProvider.parseDestination(sender, input)
.map(DestinationInstance::toString)
.toTry())
.aliases("destination", "dest")
.suggester((sender, input) -> actionHandlerProvider.getHandlerType(portal.getActionType())
.map(actionHandlerType -> actionHandlerType.suggestActions(sender, input))
.getOrElse(Collections.emptyList()))
.stringParser((sender, input, type) ->
Try.of(() -> actionHandlerProvider.getHandlerType(portal.getActionType())
.mapAttempt(actionHandlerType -> actionHandlerType.parseHandler(sender, input))
.map(ActionHandler::serialise)
.getOrThrow(failure ->
new MultiverseException(failure.getFailureMessage()))))
.build());

final ConfigNode<Boolean> checkDestinationSafety = node(ConfigNode.builder("check-destination-safety", Boolean.class)
Expand Down
Loading
Loading