diff --git a/Core/src/main/java/com/plotsquared/core/command/Add.java b/Core/src/main/java/com/plotsquared/core/command/Add.java index 45db5366d..02a7124d2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Add.java +++ b/Core/src/main/java/com/plotsquared/core/command/Add.java @@ -19,6 +19,7 @@ package com.plotsquared.core.command; import com.google.inject.Inject; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.database.DBFunc; @@ -101,9 +102,14 @@ public class Add extends Command { Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { player.sendMessage( TranslatableCaption.of("errors.invalid_player"), - TagResolver.resolver("value", Tag.inserting( - PlayerManager.resolveName(uuid).toComponent(player) - )) + PlotSquared + .platform() + .playerManager() + .getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( + "value", + Tag.inserting(caption.toComponent(player)) + )) ); iterator.remove(); continue; @@ -111,9 +117,11 @@ public class Add extends Command { if (plot.isOwner(uuid)) { player.sendMessage( TranslatableCaption.of("member.already_added"), - TagResolver.resolver("player", Tag.inserting( - PlayerManager.resolveName(uuid).toComponent(player) - )) + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( + "player", + Tag.inserting(caption.toComponent(player)) + )) ); iterator.remove(); continue; @@ -121,9 +129,11 @@ public class Add extends Command { if (plot.getMembers().contains(uuid)) { player.sendMessage( TranslatableCaption.of("member.already_added"), - TagResolver.resolver("player", Tag.inserting( - PlayerManager.resolveName(uuid).toComponent(player) - )) + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( + "player", + Tag.inserting(caption.toComponent(player)) + )) ); iterator.remove(); continue; diff --git a/Core/src/main/java/com/plotsquared/core/command/CommandCategory.java b/Core/src/main/java/com/plotsquared/core/command/CommandCategory.java index a76938577..c30ec8241 100644 --- a/Core/src/main/java/com/plotsquared/core/command/CommandCategory.java +++ b/Core/src/main/java/com/plotsquared/core/command/CommandCategory.java @@ -25,6 +25,7 @@ import com.plotsquared.core.player.PlotPlayer; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; /** * CommandCategory. @@ -82,7 +83,7 @@ public enum CommandCategory implements Caption { // TODO this method shouldn't be invoked @Deprecated @Override - public String toString() { + public @NotNull String toString() { return this.caption.getComponent(LocaleHolder.console()); } @@ -108,4 +109,5 @@ public enum CommandCategory implements Caption { return !MainCommand.getInstance().getCommands(this, player).isEmpty(); } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/Deny.java b/Core/src/main/java/com/plotsquared/core/command/Deny.java index ec3811a94..56e7c2c8a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Deny.java +++ b/Core/src/main/java/com/plotsquared/core/command/Deny.java @@ -117,10 +117,11 @@ public class Deny extends SubCommand { } else if (plot.getDenied().contains(uuid)) { player.sendMessage( TranslatableCaption.of("member.already_added"), - TagResolver.resolver( + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( "player", - Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) - ) + Tag.inserting(caption.toComponent(player)) + )) ); return; } else { diff --git a/Core/src/main/java/com/plotsquared/core/command/Owner.java b/Core/src/main/java/com/plotsquared/core/command/Owner.java index ee3c32eec..362b17654 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Owner.java +++ b/Core/src/main/java/com/plotsquared/core/command/Owner.java @@ -31,7 +31,6 @@ import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.EventDispatcher; -import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.task.TaskManager; import net.kyori.adventure.text.Component; @@ -136,10 +135,11 @@ public class Owner extends SetCommand { if (plot.isOwner(uuid)) { player.sendMessage( TranslatableCaption.of("member.already_owner"), - TagResolver.resolver( + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( "player", - Tag.inserting(PlayerManager.resolveName(uuid, false).toComponent(player)) - ) + Tag.inserting(caption.toComponent(player)) + )) ); return; } @@ -147,10 +147,11 @@ public class Owner extends SetCommand { if (other == null) { player.sendMessage( TranslatableCaption.of("errors.invalid_player_offline"), - TagResolver.resolver( + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( "player", - Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) - ) + Tag.inserting(caption.toComponent(player)) + )) ); return; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Trust.java b/Core/src/main/java/com/plotsquared/core/command/Trust.java index 9ad0d6e49..23d306ad3 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trust.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trust.java @@ -19,6 +19,7 @@ package com.plotsquared.core.command; import com.google.inject.Inject; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.database.DBFunc; @@ -103,10 +104,11 @@ public class Trust extends Command { player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { player.sendMessage( TranslatableCaption.of("errors.invalid_player"), - TagResolver.resolver( + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( "value", - Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) - ) + Tag.inserting(caption.toComponent(player)) + )) ); iterator.remove(); continue; @@ -114,10 +116,11 @@ public class Trust extends Command { if (currentPlot.isOwner(uuid)) { player.sendMessage( TranslatableCaption.of("member.already_added"), - TagResolver.resolver( - "value", - Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) - ) + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( + "player", + Tag.inserting(caption.toComponent(player)) + )) ); iterator.remove(); continue; @@ -125,10 +128,11 @@ public class Trust extends Command { if (currentPlot.getTrusted().contains(uuid)) { player.sendMessage( TranslatableCaption.of("member.already_added"), - TagResolver.resolver( - "value", - Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) - ) + PlotSquared.platform().playerManager().getUsernameCaption(uuid) + .thenApply(caption -> TagResolver.resolver( + "player", + Tag.inserting(caption.toComponent(player)) + )) ); iterator.remove(); continue; diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/Caption.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/Caption.java index 21da701ab..02155a4e9 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/caption/Caption.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/Caption.java @@ -44,4 +44,6 @@ public interface Caption { */ @NonNull Component toComponent(@NonNull LocaleHolder localeHolder); + @NonNull String toString(); + } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/StaticCaption.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/StaticCaption.java index e7f9a122d..88e69d14f 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/caption/StaticCaption.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/StaticCaption.java @@ -51,4 +51,9 @@ public final class StaticCaption implements Caption { return MiniMessage.miniMessage().deserialize(this.value); } + @Override + public @NonNull String toString() { + return "StaticCaption(" + value + ")"; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/TranslatableCaption.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/TranslatableCaption.java index bb3db5182..18a2c9fca 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/caption/TranslatableCaption.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/TranslatableCaption.java @@ -25,6 +25,7 @@ import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.checkerframework.checker.nullness.qual.NonNull; +import org.jetbrains.annotations.NotNull; import java.util.Locale; import java.util.regex.Pattern; @@ -132,4 +133,9 @@ public final class TranslatableCaption implements NamespacedCaption { return Objects.hashCode(this.getNamespace(), this.getKey()); } + @Override + public @NotNull String toString() { + return "TranslatableCaption(" + getNamespace() + ":" + getKey() + ")"; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index c583ed072..1ac4887a3 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -55,7 +55,6 @@ import com.plotsquared.core.plot.flag.implementations.TitlesFlag; import com.plotsquared.core.plot.flag.implementations.WeatherFlag; import com.plotsquared.core.plot.flag.types.TimedFlag; import com.plotsquared.core.util.EventDispatcher; -import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.world.gamemode.GameMode; @@ -63,7 +62,6 @@ import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; @@ -77,6 +75,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CompletableFuture; public class PlotListener { @@ -321,22 +320,27 @@ public class PlotListener { } if ((lastPlot != null) && plot.getId().equals(lastPlot.getId()) && plot.hasOwner()) { final UUID plotOwner = plot.getOwnerAbs(); - ComponentLike owner = PlayerManager.resolveName(plotOwner, true).toComponent(player); Caption header = fromFlag ? StaticCaption.of(title) : TranslatableCaption.of("titles" + ".title_entered_plot"); Caption subHeader = fromFlag ? StaticCaption.of(subtitle) : TranslatableCaption.of("titles" + ".title_entered_plot_sub"); - TagResolver resolver = TagResolver.builder() - .tag("plot", Tag.inserting(Component.text(lastPlot.getId().toString()))) - .tag("world", Tag.inserting(Component.text(player.getLocation().getWorldName()))) - .tag("owner", Tag.inserting(owner)) - .tag("alias", Tag.inserting(Component.text(plot.getAlias()))) - .build(); - if (Settings.Titles.TITLES_AS_ACTIONBAR) { - player.sendActionBar(header, resolver); - } else { - player.sendTitle(header, subHeader, resolver); - } + + CompletableFuture future = PlotSquared.platform().playerManager() + .getUsernameCaption(plotOwner).thenApply(caption -> TagResolver.builder() + .tag("owner", Tag.inserting(caption.toComponent(player))) + .tag("plot", Tag.inserting(Component.text(lastPlot.getId().toString()))) + .tag("world", Tag.inserting(Component.text(player.getLocation().getWorldName()))) + .tag("alias", Tag.inserting(Component.text(plot.getAlias()))) + .build() + ); + + future.whenComplete((tagResolver, throwable) -> { + if (Settings.Titles.TITLES_AS_ACTIONBAR) { + player.sendActionBar(header, tagResolver); + } else { + player.sendTitle(header, subHeader, tagResolver); + } + }); } }, TaskTime.seconds(1L)); } diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 74bb89294..483915479 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -80,6 +80,7 @@ import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -953,6 +954,52 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer, } } + /** + * Sends a message to the command caller, when the future is resolved + * + * @param caption Caption to send + * @param asyncReplacement Async variable replacement + * @return A Future to be resolved, after the message was sent + */ + public final CompletableFuture sendMessage( + @NonNull Caption caption, + CompletableFuture<@NonNull TagResolver> asyncReplacement + ) { + return sendMessage(caption, new CompletableFuture[]{asyncReplacement}); + } + + /** + * Sends a message to the command caller, when all futures are resolved + * + * @param caption Caption to send + * @param asyncReplacements Async variable replacements + * @param replacements Sync variable replacements + * @return A Future to be resolved, after the message was sent + */ + public final CompletableFuture sendMessage( + @NonNull Caption caption, + CompletableFuture<@NonNull TagResolver>[] asyncReplacements, + @NonNull TagResolver... replacements + ) { + return CompletableFuture.allOf(asyncReplacements).whenComplete((unused, throwable) -> { + Set resolvers = new HashSet<>(Arrays.asList(replacements)); + if (throwable != null) { + sendMessage( + TranslatableCaption.of("errors.error"), + TagResolver.resolver("value", Tag.inserting( + Component.text("Failed to resolve asynchronous caption replacements") + )) + ); + LOGGER.error("Failed to resolve asynchronous tagresolver(s) for " + caption, throwable); + } else { + for (final CompletableFuture asyncReplacement : asyncReplacements) { + resolvers.add(asyncReplacement.join()); + } + } + sendMessage(caption, resolvers.toArray(TagResolver[]::new)); + }); + } + // Redefine from PermissionHolder as it's required from CommandCaller @Override public boolean hasPermission(@NonNull String permission) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java b/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java index e94497da6..3fa8d3dd4 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotModificationManager.java @@ -38,7 +38,6 @@ import com.plotsquared.core.location.Location; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.queue.QueueCoordinator; -import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; import com.sk89q.worldedit.function.pattern.Pattern; @@ -59,6 +58,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -383,13 +383,17 @@ public final class PlotModificationManager { } if (createSign) { queue.setCompleteTask(() -> TaskManager.runTaskAsync(() -> { - for (Plot current : plots) { - current.getPlotModificationManager().setSign(PlayerManager.resolveName(current.getOwnerAbs()).getComponent( - LocaleHolder.console())); - } - if (whenDone != null) { - TaskManager.runTask(whenDone); - } + List> tasks = plots.stream().map(current -> PlotSquared.platform().playerManager() + .getUsernameCaption(current.getOwnerAbs()) + .thenAccept(caption -> current + .getPlotModificationManager() + .setSign(caption.getComponent(LocaleHolder.console())))) + .toList(); + CompletableFuture.allOf(tasks.toArray(CompletableFuture[]::new)).whenComplete((unused, throwable) -> { + if (whenDone != null) { + TaskManager.runTask(whenDone); + } + }); })); } else if (whenDone != null) { queue.setCompleteTask(whenDone); diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java index 1f4e98a3d..7ce2c0403 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -48,6 +48,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @@ -169,7 +170,9 @@ public abstract class PlayerManager

, T> { * @return A caption containing either the name, {@code None}, {@code Everyone} or {@code Unknown} * @see #resolveName(UUID, boolean) * @since 6.4.0 + * @deprecated Don't unnecessarily block threads and utilize playerMap - see {@link #getUsernameCaption(UUID)} */ + @Deprecated public static @NonNull Caption resolveName(final @Nullable UUID owner) { return resolveName(owner, true); } @@ -181,7 +184,9 @@ public abstract class PlayerManager

, T> { * @param blocking If the operation should block the current thread for {@link Settings.UUID#BLOCKING_TIMEOUT} milliseconds * @return A caption containing either the name, {@code None}, {@code Everyone} or {@code Unknown} * @since 6.4.0 + * @deprecated Don't unnecessarily block threads and utilize playerMap - see {@link #getUsernameCaption(UUID)} */ + @Deprecated public static @NonNull Caption resolveName(final @Nullable UUID owner, final boolean blocking) { if (owner == null) { return TranslatableCaption.of("info.none"); @@ -211,6 +216,27 @@ public abstract class PlayerManager

, T> { return StaticCaption.of(name); } + public CompletableFuture getUsernameCaption(@Nullable UUID uuid) { + if (uuid == null) { + return CompletableFuture.completedFuture(TranslatableCaption.of("info.none")); + } + if (uuid.equals(DBFunc.EVERYONE)) { + return CompletableFuture.completedFuture(TranslatableCaption.of("info.everyone")); + } + if (uuid.equals(DBFunc.SERVER)) { + return CompletableFuture.completedFuture(TranslatableCaption.of("info.server")); + } + if (playerMap.containsKey(uuid)) { + return CompletableFuture.completedFuture(StaticCaption.of(playerMap.get(uuid).getName())); + } + return PlotSquared.get().getImpromptuUUIDPipeline().getNames(Collections.singleton(uuid)).thenApply(mapping -> { + if (mapping.isEmpty()) { + return TranslatableCaption.of("info.unknown"); + } + return StaticCaption.of(mapping.get(0).username()); + }); + } + /** * Remove a player from the player map * diff --git a/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java index ed62b8799..4427ae26b 100644 --- a/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java +++ b/Core/src/main/java/com/plotsquared/core/util/placeholders/PlaceholderRegistry.java @@ -47,6 +47,7 @@ import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.UUID; +import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; /** @@ -109,9 +110,9 @@ public final class PlaceholderRegistry { if (plotOwner == null) { return legacyComponent(TranslatableCaption.of("generic.generic_unowned"), player); } - try { - return PlayerManager.resolveName(plotOwner, false).getComponent(player); + return PlotSquared.platform().playerManager().getUsernameCaption(plotOwner) + .get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS).getComponent(player); } catch (final Exception ignored) { } return legacyComponent(TranslatableCaption.of("info.unknown"), player);