From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Tue, 1 Feb 2022 15:51:55 -0700 Subject: [PATCH] API for creating command sender which forwards feedback diff --git a/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java new file mode 100644 index 0000000000000000000000000000000000000000..ed3d488c6581df5eac425d9cccb8e741a52e91d5 --- /dev/null +++ b/src/main/java/io/papermc/paper/commands/FeedbackForwardingSender.java @@ -0,0 +1,112 @@ +package io.papermc.paper.commands; + +import io.papermc.paper.adventure.PaperAdventure; +import java.util.UUID; +import java.util.function.Consumer; +import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.command.ServerCommandSender; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public final class FeedbackForwardingSender extends ServerCommandSender { + private final Consumer feedback; + private final CraftServer server; + + public FeedbackForwardingSender(final Consumer feedback, final CraftServer server) { + super(((ServerCommandSender) server.getConsoleSender()).perm); + this.server = server; + this.feedback = feedback; + } + + @Override + public void sendMessage(final String message) { + this.sendMessage(LegacyComponentSerializer.legacySection().deserialize(message)); + } + + @Override + public void sendMessage(final String... messages) { + for (final String message : messages) { + this.sendMessage(message); + } + } + + @Override + public void sendMessage(final Identity identity, final Component message, final MessageType type) { + this.feedback.accept(message); + } + + @Override + public String getName() { + return "FeedbackForwardingSender"; + } + + @Override + public Component name() { + return Component.text(this.getName()); + } + + @Override + public boolean isOp() { + return true; + } + + @Override + public void setOp(final boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of " + this.getClass().getName()); + } + + public CommandSourceStack asVanilla() { + final @Nullable ServerLevel overworld = this.server.getServer().overworld(); + return new CommandSourceStack( + new Source(this), + overworld == null ? Vec3.ZERO : Vec3.atLowerCornerOf(overworld.getSharedSpawnPos()), + Vec2.ZERO, + overworld, + 4, + this.getName(), + new TextComponent(this.getName()), + this.server.getServer(), + null + ); + } + + private record Source(FeedbackForwardingSender sender) implements CommandSource { + @Override + public void sendMessage(final net.minecraft.network.chat.Component message, final UUID sender) { + this.sender.sendMessage(Identity.identity(sender), PaperAdventure.asAdventure(message)); + } + + @Override + public boolean acceptsSuccess() { + return true; + } + + @Override + public boolean acceptsFailure() { + return true; + } + + @Override + public boolean shouldInformAdmins() { + return false; + } + + @Override + public CommandSender getBukkitSender(final CommandSourceStack stack) { + return this.sender; + } + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index b4133f8dde5edb75b8d2d1008c50db7810276913..d9bfdeba8eaa8ab750b5037ff3d3a82a445adc2d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1988,6 +1988,13 @@ public final class CraftServer implements Server { return console.console; } + // Paper start + @Override + public CommandSender createCommandSender(final java.util.function.Consumer feedback) { + return new io.papermc.paper.commands.FeedbackForwardingSender(feedback, this); + } + // Paper end + public EntityMetadataStore getEntityMetadata() { return this.entityMetadata; } diff --git a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java index eaff8df6c8c12c64e005a68a02e2e35ed88f757c..1c638a4b1f2c841928d8b2a7ae43e4ebb1f7eac7 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java +++ b/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java @@ -13,9 +13,15 @@ import org.bukkit.plugin.Plugin; public abstract class ServerCommandSender implements CommandSender { private static PermissibleBase blockPermInst; - private final PermissibleBase perm; + public final PermissibleBase perm; // Paper private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers + // Paper start + public ServerCommandSender(final PermissibleBase permissibleBase) { + this.perm = permissibleBase; + } + // Paper end + public ServerCommandSender() { if (this instanceof CraftBlockCommandSender) { if (ServerCommandSender.blockPermInst == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java index 4aa1dc543950b5de64345b3403a6d0bc41c521df..4525fb3bc9b137bce3b59310a8aecca96d6ad5ba 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -84,6 +84,11 @@ public final class VanillaCommandWrapper extends BukkitCommand { if (sender instanceof ProxiedCommandSender) { return ((ProxiedNativeCommandSender) sender).getHandle(); } + // Paper start + if (sender instanceof io.papermc.paper.commands.FeedbackForwardingSender feedback) { + return feedback.asVanilla(); + } + // Paper end throw new IllegalArgumentException("Cannot make " + sender + " a vanilla command listener"); }