fix: player placeholders in command responses

This commit is contained in:
Pierre Maurice Schwang 2023-10-02 23:41:21 +02:00
parent a3bc3968a5
commit 42c5f38788
13 changed files with 168 additions and 55 deletions

View File

@ -19,6 +19,7 @@
package com.plotsquared.core.command; package com.plotsquared.core.command;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.database.DBFunc;
@ -101,9 +102,14 @@ public class Add extends Command {
Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { Permission.PERMISSION_ADMIN_COMMAND_TRUST))) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("errors.invalid_player"), TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver("value", Tag.inserting( PlotSquared
PlayerManager.resolveName(uuid).toComponent(player) .platform()
)) .playerManager()
.getUsernameCaption(uuid)
.thenApply(caption -> TagResolver.resolver(
"value",
Tag.inserting(caption.toComponent(player))
))
); );
iterator.remove(); iterator.remove();
continue; continue;
@ -111,9 +117,11 @@ public class Add extends Command {
if (plot.isOwner(uuid)) { if (plot.isOwner(uuid)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("member.already_added"), TranslatableCaption.of("member.already_added"),
TagResolver.resolver("player", Tag.inserting( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
PlayerManager.resolveName(uuid).toComponent(player) .thenApply(caption -> TagResolver.resolver(
)) "player",
Tag.inserting(caption.toComponent(player))
))
); );
iterator.remove(); iterator.remove();
continue; continue;
@ -121,9 +129,11 @@ public class Add extends Command {
if (plot.getMembers().contains(uuid)) { if (plot.getMembers().contains(uuid)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("member.already_added"), TranslatableCaption.of("member.already_added"),
TagResolver.resolver("player", Tag.inserting( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
PlayerManager.resolveName(uuid).toComponent(player) .thenApply(caption -> TagResolver.resolver(
)) "player",
Tag.inserting(caption.toComponent(player))
))
); );
iterator.remove(); iterator.remove();
continue; continue;

View File

@ -25,6 +25,7 @@ import com.plotsquared.core.player.PlotPlayer;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
/** /**
* CommandCategory. * CommandCategory.
@ -82,7 +83,7 @@ public enum CommandCategory implements Caption {
// TODO this method shouldn't be invoked // TODO this method shouldn't be invoked
@Deprecated @Deprecated
@Override @Override
public String toString() { public @NotNull String toString() {
return this.caption.getComponent(LocaleHolder.console()); return this.caption.getComponent(LocaleHolder.console());
} }
@ -108,4 +109,5 @@ public enum CommandCategory implements Caption {
return !MainCommand.getInstance().getCommands(this, player).isEmpty(); return !MainCommand.getInstance().getCommands(this, player).isEmpty();
} }
} }

View File

@ -117,10 +117,11 @@ public class Deny extends SubCommand {
} else if (plot.getDenied().contains(uuid)) { } else if (plot.getDenied().contains(uuid)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("member.already_added"), TranslatableCaption.of("member.already_added"),
TagResolver.resolver( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
.thenApply(caption -> TagResolver.resolver(
"player", "player",
Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) Tag.inserting(caption.toComponent(player))
) ))
); );
return; return;
} else { } else {

View File

@ -31,7 +31,6 @@ import com.plotsquared.core.player.PlayerMetaDataKeys;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.PlayerManager;
import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.TabCompletions;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -136,10 +135,11 @@ public class Owner extends SetCommand {
if (plot.isOwner(uuid)) { if (plot.isOwner(uuid)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("member.already_owner"), TranslatableCaption.of("member.already_owner"),
TagResolver.resolver( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
.thenApply(caption -> TagResolver.resolver(
"player", "player",
Tag.inserting(PlayerManager.resolveName(uuid, false).toComponent(player)) Tag.inserting(caption.toComponent(player))
) ))
); );
return; return;
} }
@ -147,10 +147,11 @@ public class Owner extends SetCommand {
if (other == null) { if (other == null) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("errors.invalid_player_offline"), TranslatableCaption.of("errors.invalid_player_offline"),
TagResolver.resolver( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
.thenApply(caption -> TagResolver.resolver(
"player", "player",
Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) Tag.inserting(caption.toComponent(player))
) ))
); );
return; return;
} }

View File

@ -19,6 +19,7 @@
package com.plotsquared.core.command; package com.plotsquared.core.command;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc; 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.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST))) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("errors.invalid_player"), TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
.thenApply(caption -> TagResolver.resolver(
"value", "value",
Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) Tag.inserting(caption.toComponent(player))
) ))
); );
iterator.remove(); iterator.remove();
continue; continue;
@ -114,10 +116,11 @@ public class Trust extends Command {
if (currentPlot.isOwner(uuid)) { if (currentPlot.isOwner(uuid)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("member.already_added"), TranslatableCaption.of("member.already_added"),
TagResolver.resolver( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
"value", .thenApply(caption -> TagResolver.resolver(
Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) "player",
) Tag.inserting(caption.toComponent(player))
))
); );
iterator.remove(); iterator.remove();
continue; continue;
@ -125,10 +128,11 @@ public class Trust extends Command {
if (currentPlot.getTrusted().contains(uuid)) { if (currentPlot.getTrusted().contains(uuid)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("member.already_added"), TranslatableCaption.of("member.already_added"),
TagResolver.resolver( PlotSquared.platform().playerManager().getUsernameCaption(uuid)
"value", .thenApply(caption -> TagResolver.resolver(
Tag.inserting(PlayerManager.resolveName(uuid).toComponent(player)) "player",
) Tag.inserting(caption.toComponent(player))
))
); );
iterator.remove(); iterator.remove();
continue; continue;

View File

@ -44,4 +44,6 @@ public interface Caption {
*/ */
@NonNull Component toComponent(@NonNull LocaleHolder localeHolder); @NonNull Component toComponent(@NonNull LocaleHolder localeHolder);
@NonNull String toString();
} }

View File

@ -51,4 +51,9 @@ public final class StaticCaption implements Caption {
return MiniMessage.miniMessage().deserialize(this.value); return MiniMessage.miniMessage().deserialize(this.value);
} }
@Override
public @NonNull String toString() {
return "StaticCaption(" + value + ")";
}
} }

View File

@ -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.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -132,4 +133,9 @@ public final class TranslatableCaption implements NamespacedCaption {
return Objects.hashCode(this.getNamespace(), this.getKey()); return Objects.hashCode(this.getNamespace(), this.getKey());
} }
@Override
public @NotNull String toString() {
return "TranslatableCaption(" + getNamespace() + ":" + getKey() + ")";
}
} }

View File

@ -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.implementations.WeatherFlag;
import com.plotsquared.core.plot.flag.types.TimedFlag; import com.plotsquared.core.plot.flag.types.TimedFlag;
import com.plotsquared.core.util.EventDispatcher; 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.TaskManager;
import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.world.gamemode.GameMode; 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.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.item.ItemTypes;
import net.kyori.adventure.text.Component; 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.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
@ -77,6 +75,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class PlotListener { public class PlotListener {
@ -321,22 +320,27 @@ public class PlotListener {
} }
if ((lastPlot != null) && plot.getId().equals(lastPlot.getId()) && plot.hasOwner()) { if ((lastPlot != null) && plot.getId().equals(lastPlot.getId()) && plot.hasOwner()) {
final UUID plotOwner = plot.getOwnerAbs(); final UUID plotOwner = plot.getOwnerAbs();
ComponentLike owner = PlayerManager.resolveName(plotOwner, true).toComponent(player);
Caption header = fromFlag ? StaticCaption.of(title) : TranslatableCaption.of("titles" + Caption header = fromFlag ? StaticCaption.of(title) : TranslatableCaption.of("titles" +
".title_entered_plot"); ".title_entered_plot");
Caption subHeader = fromFlag ? StaticCaption.of(subtitle) : TranslatableCaption.of("titles" + Caption subHeader = fromFlag ? StaticCaption.of(subtitle) : TranslatableCaption.of("titles" +
".title_entered_plot_sub"); ".title_entered_plot_sub");
TagResolver resolver = TagResolver.builder()
.tag("plot", Tag.inserting(Component.text(lastPlot.getId().toString()))) CompletableFuture<TagResolver> future = PlotSquared.platform().playerManager()
.tag("world", Tag.inserting(Component.text(player.getLocation().getWorldName()))) .getUsernameCaption(plotOwner).thenApply(caption -> TagResolver.builder()
.tag("owner", Tag.inserting(owner)) .tag("owner", Tag.inserting(caption.toComponent(player)))
.tag("alias", Tag.inserting(Component.text(plot.getAlias()))) .tag("plot", Tag.inserting(Component.text(lastPlot.getId().toString())))
.build(); .tag("world", Tag.inserting(Component.text(player.getLocation().getWorldName())))
if (Settings.Titles.TITLES_AS_ACTIONBAR) { .tag("alias", Tag.inserting(Component.text(plot.getAlias())))
player.sendActionBar(header, resolver); .build()
} else { );
player.sendTitle(header, subHeader, resolver);
} future.whenComplete((tagResolver, throwable) -> {
if (Settings.Titles.TITLES_AS_ACTIONBAR) {
player.sendActionBar(header, tagResolver);
} else {
player.sendTitle(header, subHeader, tagResolver);
}
});
} }
}, TaskTime.seconds(1L)); }, TaskTime.seconds(1L));
} }

View File

@ -80,6 +80,7 @@ import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -953,6 +954,52 @@ public abstract class PlotPlayer<P> 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<Void> 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<Void> sendMessage(
@NonNull Caption caption,
CompletableFuture<@NonNull TagResolver>[] asyncReplacements,
@NonNull TagResolver... replacements
) {
return CompletableFuture.allOf(asyncReplacements).whenComplete((unused, throwable) -> {
Set<TagResolver> 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<TagResolver> asyncReplacement : asyncReplacements) {
resolvers.add(asyncReplacement.join());
}
}
sendMessage(caption, resolvers.toArray(TagResolver[]::new));
});
}
// Redefine from PermissionHolder as it's required from CommandCaller // Redefine from PermissionHolder as it's required from CommandCaller
@Override @Override
public boolean hasPermission(@NonNull String permission) { public boolean hasPermission(@NonNull String permission) {

View File

@ -38,7 +38,6 @@ import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.queue.QueueCoordinator; 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.TaskManager;
import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
@ -59,6 +58,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -383,13 +383,17 @@ public final class PlotModificationManager {
} }
if (createSign) { if (createSign) {
queue.setCompleteTask(() -> TaskManager.runTaskAsync(() -> { queue.setCompleteTask(() -> TaskManager.runTaskAsync(() -> {
for (Plot current : plots) { List<CompletableFuture<Void>> tasks = plots.stream().map(current -> PlotSquared.platform().playerManager()
current.getPlotModificationManager().setSign(PlayerManager.resolveName(current.getOwnerAbs()).getComponent( .getUsernameCaption(current.getOwnerAbs())
LocaleHolder.console())); .thenAccept(caption -> current
} .getPlotModificationManager()
if (whenDone != null) { .setSign(caption.getComponent(LocaleHolder.console()))))
TaskManager.runTask(whenDone); .toList();
} CompletableFuture.allOf(tasks.toArray(CompletableFuture[]::new)).whenComplete((unused, throwable) -> {
if (whenDone != null) {
TaskManager.runTask(whenDone);
}
});
})); }));
} else if (whenDone != null) { } else if (whenDone != null) {
queue.setCompleteTask(whenDone); queue.setCompleteTask(whenDone);

View File

@ -48,6 +48,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -169,7 +170,9 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
* @return A caption containing either the name, {@code None}, {@code Everyone} or {@code Unknown} * @return A caption containing either the name, {@code None}, {@code Everyone} or {@code Unknown}
* @see #resolveName(UUID, boolean) * @see #resolveName(UUID, boolean)
* @since 6.4.0 * @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) { public static @NonNull Caption resolveName(final @Nullable UUID owner) {
return resolveName(owner, true); return resolveName(owner, true);
} }
@ -181,7 +184,9 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
* @param blocking If the operation should block the current thread for {@link Settings.UUID#BLOCKING_TIMEOUT} milliseconds * @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} * @return A caption containing either the name, {@code None}, {@code Everyone} or {@code Unknown}
* @since 6.4.0 * @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) { public static @NonNull Caption resolveName(final @Nullable UUID owner, final boolean blocking) {
if (owner == null) { if (owner == null) {
return TranslatableCaption.of("info.none"); return TranslatableCaption.of("info.none");
@ -211,6 +216,27 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
return StaticCaption.of(name); return StaticCaption.of(name);
} }
public CompletableFuture<Caption> 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 * Remove a player from the player map
* *

View File

@ -47,6 +47,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction; import java.util.function.BiFunction;
/** /**
@ -109,9 +110,9 @@ public final class PlaceholderRegistry {
if (plotOwner == null) { if (plotOwner == null) {
return legacyComponent(TranslatableCaption.of("generic.generic_unowned"), player); return legacyComponent(TranslatableCaption.of("generic.generic_unowned"), player);
} }
try { 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) { } catch (final Exception ignored) {
} }
return legacyComponent(TranslatableCaption.of("info.unknown"), player); return legacyComponent(TranslatableCaption.of("info.unknown"), player);