diff --git a/build.gradle b/build.gradle index 68a52f42..f1f57907 100644 --- a/build.gradle +++ b/build.gradle @@ -11,10 +11,6 @@ repositories { name = 'enginehub' url = uri('https://maven.enginehub.org/repo/') } - maven { - name = 'benthecat' - url = uri('https://repo.c0ding.party/multiverse-beta') - } maven { name = "helpchatRepoReleases" url = uri("https://repo.helpch.at/releases/") diff --git a/src/main/java/org/mvplugins/multiverse/portals/MVPortal.java b/src/main/java/org/mvplugins/multiverse/portals/MVPortal.java index c17df4ff..161e9fa7 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/MVPortal.java +++ b/src/main/java/org/mvplugins/multiverse/portals/MVPortal.java @@ -39,6 +39,9 @@ import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; import org.mvplugins.multiverse.core.world.MultiverseWorld; import org.mvplugins.multiverse.core.world.WorldManager; +import org.mvplugins.multiverse.external.acf.locales.MessageKey; +import org.mvplugins.multiverse.external.acf.locales.MessageKeyProvider; +import org.mvplugins.multiverse.external.vavr.control.Either; import org.mvplugins.multiverse.external.vavr.control.Option; import org.mvplugins.multiverse.external.vavr.control.Try; import org.mvplugins.multiverse.portals.action.ActionFailureReason; @@ -55,6 +58,7 @@ import org.bukkit.permissions.PermissionDefault; import org.bukkit.util.Vector; +import org.mvplugins.multiverse.portals.locale.MVPi18n; import org.mvplugins.multiverse.portals.utils.MultiverseRegion; public final class MVPortal { @@ -153,6 +157,12 @@ private MemoryConfigurationHandle setUpConfigHandle(ConfigurationSection portalS .addVersionMigrator(VersionMigrator.builder(1.2) .addAction(MoveMigratorAction.of("destination", "action")) .build()) + .addVersionMigrator(VersionMigrator.builder(1.3) + .addAction(MoveMigratorAction.of("action", "action.value")) + .addAction(MoveMigratorAction.of("action-type", "action.type")) + .addAction(MoveMigratorAction.of("currency", "entry-fee.currency")) + .addAction(MoveMigratorAction.of("price", "entry-fee.price")) + .build()) .build()) .build(); } @@ -262,6 +272,39 @@ public double getPrice() { return this.configHandle.get(configNodes.price); } + @ApiStatus.AvailableSince("5.3") + public Try setActionSuccessMessage(String message) { + return this.configHandle.set(this.configNodes.actionSuccessMessage, message); + } + + @ApiStatus.AvailableSince("5.3") + public Option> getActionSuccessMessage() { + return getMessageEither(this.configHandle.get(this.configNodes.actionSuccessMessage), MVPi18n.PORTAL_ACTION_SUCCESS); + } + + @ApiStatus.AvailableSince("5.3") + public Try setNoPermissionMessage(String message) { + return this.configHandle.set(this.configNodes.noPermissionMessage, message); + } + + @ApiStatus.AvailableSince("5.3") + public Option> getNoPermissionMessage() { + return getMessageEither(this.configHandle.get(this.configNodes.noPermissionMessage),MVPi18n.PORTAL_PERMISSION_DENIED); + } + + private Option> getMessageEither(String message, MessageKeyProvider defaultMessageKey) { + if (message == null || message.equalsIgnoreCase("@disabled")) { + return Option.none(); + } + if (message.equalsIgnoreCase("@default")) { + return Option.of(Either.left(defaultMessageKey)); + } + if (message.startsWith("@@")) { + return Option.of(Either.left(MessageKey.of(message.substring(2)))); + } + return Option.of(Either.right(message)); + } + /** * * @param locationString diff --git a/src/main/java/org/mvplugins/multiverse/portals/MVPortalNodes.java b/src/main/java/org/mvplugins/multiverse/portals/MVPortalNodes.java index ef1c461c..1fe43abb 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/MVPortalNodes.java +++ b/src/main/java/org/mvplugins/multiverse/portals/MVPortalNodes.java @@ -39,27 +39,40 @@ private N node(N node) { return node; } - final ConfigNode currency = node(ConfigNode.builder("currency", Material.class) - .defaultValue(Material.AIR) - .aliases("curr") + final ConfigNode actionType = node(ConfigNode.builder("action.type", String.class) + .name("action-type") + .suggester(input -> actionHandlerProvider.getAllHandlerTypeNames()) + .defaultValue("multiverse-destination") .build()); - final ConfigNode price = node(ConfigNode.builder("price", Double.class) - .defaultValue(0.0) + final ConfigNode action = node(ConfigNode.builder("action.value", String.class) + .name("action") + .defaultValue("") + .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 safeTeleport = node(ConfigNode.builder("safe-teleport", Boolean.class) + final ConfigNode checkDestinationSafety = node(ConfigNode.builder("check-destination-safety", Boolean.class) .defaultValue(true) - .aliases("safe") .build()); - final ConfigNode teleportNonPlayers = node(ConfigNode.builder("teleport-non-players", Boolean.class) - .defaultValue(false) - .aliases("telenonplayers") + final ConfigNode currency = node(ConfigNode.builder("entry-fee.currency", Material.class) + .name("currency") + .defaultValue(Material.AIR) + .aliases("curr") .build()); - final ConfigNode owner = node(ConfigNode.builder("owner", String.class) - .defaultValue("") + final ConfigNode price = node(ConfigNode.builder("entry-fee.price", Double.class) + .name("price") + .defaultValue(0.0) .build()); final ConfigNode location = node(ConfigNode.builder("location", String.class) @@ -91,30 +104,32 @@ private N node(N node) { } return Try.success(portalLocation.toString()); }) - .onSetValue((oldValue, newValue) -> portal.setPortalLocationInternal(PortalLocation.parseLocation(newValue))) + .onLoadAndChange((oldValue, newValue) -> + portal.setPortalLocationInternal(PortalLocation.parseLocation(newValue))) .build()); - final ConfigNode actionType = node(ConfigNode.builder("action-type", String.class) - .suggester(input -> actionHandlerProvider.getAllHandlerTypeNames()) - .defaultValue("multiverse-destination") + final ConfigNode actionSuccessMessage = node(ConfigNode.builder("message.action-success", String.class) + .name("action-success-message") + .defaultValue("@disabled") .build()); - final ConfigNode action = node(ConfigNode.builder("action", String.class) + final ConfigNode noPermissionMessage = node(ConfigNode.builder("message.no-permission", String.class) + .name("no-permission-message") + .defaultValue("@default") + .build()); + + final ConfigNode owner = node(ConfigNode.builder("owner", String.class) .defaultValue("") - .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 checkDestinationSafety = node(ConfigNode.builder("check-destination-safety", Boolean.class) + final ConfigNode safeTeleport = node(ConfigNode.builder("safe-teleport", Boolean.class) .defaultValue(true) + .aliases("safe") + .build()); + + final ConfigNode teleportNonPlayers = node(ConfigNode.builder("teleport-non-players", Boolean.class) + .defaultValue(false) + .aliases("telenonplayers") .build()); final ConfigNode version = node(ConfigNode.builder("version", Double.class) diff --git a/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfig.java b/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfig.java index de49de96..a4fd7720 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfig.java +++ b/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfig.java @@ -11,6 +11,7 @@ import org.mvplugins.multiverse.core.config.migration.ConfigMigrator; import org.mvplugins.multiverse.core.config.migration.VersionMigrator; import org.mvplugins.multiverse.core.config.migration.action.MoveMigratorAction; +import org.mvplugins.multiverse.core.config.migration.action.SetMigratorAction; import org.mvplugins.multiverse.external.jakarta.inject.Inject; import org.mvplugins.multiverse.external.vavr.control.Try; import org.mvplugins.multiverse.portals.MultiversePortals; @@ -51,6 +52,9 @@ public final class PortalsConfig { .addAction(MoveMigratorAction.of("netheranimation", "portal-usage.nether-animation")) .addAction(MoveMigratorAction.of("framematerials", "portal-creation.frame-materials")) .build()) + .addVersionMigrator(VersionMigrator.builder(5.1) + .addAction(SetMigratorAction.of("portal-usage.send-no-permission-messages", false)) + .build()) .build()) .build(); this.stringPropertyHandle = new StringPropertyHandle(configHandle); @@ -203,6 +207,29 @@ public Try setEnforcePortalAccess(boolean enforcePortalAccess) { return configHandle.set(configNodes.enforcePortalAccess, enforcePortalAccess); } + /** + * + * @return + * + * @since 5.3 + */ + @ApiStatus.AvailableSince("5.3") + public boolean getSendNoPermissionMessages() { + return configHandle.get(configNodes.sendNoPermissionMessages); + } + + /** + * + * @param sendNoPermissionMessages + * @return + * + * @since 5.3 + */ + @ApiStatus.AvailableSince("5.3") + public Try setSendNoPermissionMessages(boolean sendNoPermissionMessages) { + return configHandle.set(configNodes.sendNoPermissionMessages, sendNoPermissionMessages); + } + /** * * @return diff --git a/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfigNodes.java b/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfigNodes.java index bfe9ead5..be8d045f 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfigNodes.java +++ b/src/main/java/org/mvplugins/multiverse/portals/config/PortalsConfigNodes.java @@ -122,6 +122,15 @@ public Object serialize(Material material, Class aClass) { .onSetValue((oldValue, newValue) -> MultiversePortals.EnforcePortalAccess = newValue) .build()); + final ConfigNode sendNoPermissionMessages = node(ConfigNode.builder("portal-usage.send-no-permission-messages", Boolean.class) + .comment("") + .comment("This is a global toggle to disable the sending of no permission messages for all portals.") + .comment("This is only applicable if `enforce-portal-access` is enabled above, else permission checks will not happen anyways.") + .comment("If you are looking to customize/disable specific portal's message, use each portal's `no-permission-message` property.") + .defaultValue(true) + .name("send-no-permission-messages") + .build()); + final ConfigNode portalCooldown = node(ConfigNode.builder("portal-usage.portal-cooldown", Integer.class) .comment("") .comment("The time (in milliseconds) a player must wait between using a mvportal.") diff --git a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityMoveListener.java b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityMoveListener.java index f8f9498b..4c74ab85 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityMoveListener.java +++ b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityMoveListener.java @@ -55,7 +55,8 @@ public void onEvent(EntityMoveEvent event) { Logging.fine("[EntityMoveEvent] Portal action for entity: " + entity); helper.stateSuccess(entity.getName(), portal.getName()); - portal.runActionFor(entity); + portal.runActionFor(entity) + .onSuccess(() -> helper.sendActionSuccessMessage(portal, entity)); } }; } diff --git a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityPortalListener.java b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityPortalListener.java index cdfda536..349f0ffb 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityPortalListener.java +++ b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPEntityPortalListener.java @@ -64,7 +64,11 @@ void entityPortal(EntityPortalEvent event) { Logging.fine("[EntityPortalEvent] Portal action for entity: " + entity); helper.stateSuccess(entity.getName(), portal.getName()); + var finalPortal = portal; portal.runActionFor(entity) - .onSuccess(() -> event.setCancelled(true)); + .onSuccess(() -> { + helper.sendActionSuccessMessage(finalPortal, entity); + event.setCancelled(true); + }); } } diff --git a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerMoveListener.java b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerMoveListener.java index d382a375..63bb47ab 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerMoveListener.java +++ b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerMoveListener.java @@ -96,6 +96,7 @@ void playerMove(PlayerMoveEvent event) { } Logging.fine("[PlayerMoveEvent] Portal action for player: " + player); - portal.runActionFor(player); + portal.runActionFor(player) + .onSuccess(() -> helper.sendActionSuccessMessage(portal, player)); } } diff --git a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerPortalListener.java b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerPortalListener.java index 0a6c9e19..761a6c78 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerPortalListener.java +++ b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPPlayerPortalListener.java @@ -102,8 +102,10 @@ void playerPortal(PlayerPortalEvent event) { Logging.fine("[PlayerPortalEvent] Portal action for player: " + player); helper.stateSuccess(player.getDisplayName(), portal.getName()); + var finalPortal = portal; portal.runActionFor(player) .onSuccess(() -> { + helper.sendActionSuccessMessage(finalPortal, player); event.setCancelled(true); }); } diff --git a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPVehicleListener.java b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPVehicleListener.java index de55371d..b976381f 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPVehicleListener.java +++ b/src/main/java/org/mvplugins/multiverse/portals/listeners/MVPVehicleListener.java @@ -101,7 +101,9 @@ void vehicleMove(VehicleMoveEvent event) { Logging.fine("[VehicleMoveEvent] Portal action for vehicle: " + vehicle); helper.stateSuccess(vehicle.getName(), portal.getName()); portal.runActionFor(vehicle) - .onSuccess(() -> playerPassengers.forEach(player -> - plugin.getPortalSession(player).setTeleportTime(new Date()))); + .onSuccess(() -> playerPassengers.forEach(player -> { + helper.sendActionSuccessMessage(portal, player); + plugin.getPortalSession(player).setTeleportTime(new Date()); + })); } } diff --git a/src/main/java/org/mvplugins/multiverse/portals/listeners/PortalListenerHelper.java b/src/main/java/org/mvplugins/multiverse/portals/listeners/PortalListenerHelper.java index e5d1df56..41b4eb39 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/listeners/PortalListenerHelper.java +++ b/src/main/java/org/mvplugins/multiverse/portals/listeners/PortalListenerHelper.java @@ -2,14 +2,19 @@ import com.dumptruckman.minecraft.util.Logging; import org.bukkit.Material; +import org.bukkit.command.CommandSender; import org.mvplugins.multiverse.core.economy.MVEconomist; import org.mvplugins.multiverse.core.command.MVCommandIssuer; import org.mvplugins.multiverse.core.command.MVCommandManager; import org.mvplugins.multiverse.core.locale.message.Message; +import org.mvplugins.multiverse.core.locale.message.MessageReplacement; import org.mvplugins.multiverse.core.locale.message.MessageReplacement.Replace; +import org.mvplugins.multiverse.external.acf.locales.MessageKeyProvider; import org.mvplugins.multiverse.external.jakarta.inject.Inject; import org.mvplugins.multiverse.external.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; +import org.mvplugins.multiverse.external.vavr.control.Either; +import org.mvplugins.multiverse.external.vavr.control.Option; import org.mvplugins.multiverse.portals.MVPortal; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -53,10 +58,30 @@ void stateFailure(String playerName, String portalName) { playerName, portalName)); } + private void sendEitherMessage(CommandSender sender, MVPortal portal, Option> message) { + MVCommandIssuer issuer = commandManager.getCommandIssuer(sender); + var replacements = new MessageReplacement[]{ + Replace.PLAYER.with(sender.getName()), + replace("{portal}").with(portal.getName()), + }; + message.peek(either -> either + .peek(msg -> issuer.sendMessage(msg, replacements)) + .peekLeft(key -> issuer.sendMessage(key, replacements))); + } + + void sendActionSuccessMessage(MVPortal portal, CommandSender sender) { + sendEitherMessage(sender, portal, portal.getActionSuccessMessage()); + } + PortalUseResult checkPlayerCanUsePortal(MVPortal portal, Player player) { + MVCommandIssuer issuer = commandManager.getCommandIssuer(player); + // If they're using Access and they don't have permission and they're NOT exempt, return, they're not allowed to tp. // No longer checking exemption status if (portalsConfig.getEnforcePortalAccess() && !player.hasPermission(portal.getPermission())) { + if (portalsConfig.getSendNoPermissionMessages()) { + sendEitherMessage(player, portal, portal.getNoPermissionMessage()); + } stateFailure(player.getDisplayName(), portal.getName()); return PortalUseResult.CANNOT_USE; } @@ -70,7 +95,6 @@ PortalUseResult checkPlayerCanUsePortal(MVPortal portal, Player player) { } if (price > 0D && !economist.isPlayerWealthyEnough(player, price, currency)) { - MVCommandIssuer issuer = commandManager.getCommandIssuer(player); Message message = Message.of(MVPi18n.PORTAL_INSUFFICIENTFUNDS, replace("{price}").with(economist.formatPrice(price, currency)), Replace.NAME.with(portal.getName())); diff --git a/src/main/java/org/mvplugins/multiverse/portals/locale/MVPi18n.java b/src/main/java/org/mvplugins/multiverse/portals/locale/MVPi18n.java index c474d7c4..7333c941 100644 --- a/src/main/java/org/mvplugins/multiverse/portals/locale/MVPi18n.java +++ b/src/main/java/org/mvplugins/multiverse/portals/locale/MVPi18n.java @@ -141,6 +141,8 @@ public enum MVPi18n implements MessageKeyProvider { ACTION_SERVER_DESCRIPTION, // Portal use + PORTAL_ACTION_SUCCESS, + PORTAL_PERMISSION_DENIED, PORTAL_FRAME_INVALID, PORTAL_DESTINATION_INVALID, PORTAL_INSUFFICIENTFUNDS, diff --git a/src/main/resources/multiverse-portals_en.properties b/src/main/resources/multiverse-portals_en.properties index f89a111f..61b66182 100644 --- a/src/main/resources/multiverse-portals_en.properties +++ b/src/main/resources/multiverse-portals_en.properties @@ -120,6 +120,8 @@ mv-portals.action.server.proxyunknownerror=An unknown error occurred while sendi mv-portals.action.server.description=&bTransfer to &6{name}&b server # Portal use +mv-portals.portal.action.success=&aYou have successfully used &f{portal} portal&a! +mv-portals.portal.permission.denied=&cYou do not have permission to use this portal. mv-portals.portal.frame.invalid=This portal's frame is made of an &cincorrect material. You should exit it now. mv-portals.portal.destination.invalid=This Multiverse Portal does not have a valid destination! mv-portals.portal.insufficientfunds=You need {price} to enter the {name} portal.