From 473f9ffa3529a96aaa76f742ebe3ef49910e839c Mon Sep 17 00:00:00 2001 From: Josh Taylor Date: Mon, 5 Aug 2024 18:33:09 +0100 Subject: [PATCH] feat(paper): add a simple sender mapper designed for use with the modern paper command manager and provides various sender mappings such as PlayerSource and ConsoleSource --------- Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com> --- .../paper/util/sender/ConsoleSource.java | 46 ++++++++++ .../cloud/paper/util/sender/EntitySource.java | 50 +++++++++++ .../paper/util/sender/GenericSource.java | 53 ++++++++++++ .../util/sender/PaperSimpleSenderMapper.java | 84 +++++++++++++++++++ .../cloud/paper/util/sender/PlayerSource.java | 45 ++++++++++ .../cloud/paper/util/sender/Source.java | 53 ++++++++++++ .../cloud/paper/util/sender/package-info.java | 5 ++ .../cloud/examples/paper/PaperPlugin.java | 7 +- .../cloud/examples/paper/PluginBootstrap.java | 31 +++++-- 9 files changed, 365 insertions(+), 9 deletions(-) create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/ConsoleSource.java create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/EntitySource.java create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/GenericSource.java create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PaperSimpleSenderMapper.java create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PlayerSource.java create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/Source.java create mode 100644 cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/package-info.java diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/ConsoleSource.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/ConsoleSource.java new file mode 100644 index 00000000..ebafe437 --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/ConsoleSource.java @@ -0,0 +1,46 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.paper.util.sender; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.ConsoleCommandSender; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Specialized variant of {@link Source}, for when the {@link CommandSourceStack#getSender() sender} is a + * {@link ConsoleCommandSender}. + */ +@SuppressWarnings("UnstableApiUsage") +public final class ConsoleSource extends GenericSource { + + ConsoleSource(final CommandSourceStack commandSourceStack) { + super(commandSourceStack); + } + + @Override + public @NonNull ConsoleCommandSender source() { + return (ConsoleCommandSender) super.source(); + } + +} diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/EntitySource.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/EntitySource.java new file mode 100644 index 00000000..16f04305 --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/EntitySource.java @@ -0,0 +1,50 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.paper.util.sender; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.entity.Entity; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Specialized variant of {@link Source}, for when the {@link CommandSourceStack#getSender() sender} is + * an {@link Entity}. + */ +@SuppressWarnings("UnstableApiUsage") +public class EntitySource extends GenericSource { + + EntitySource(final CommandSourceStack commandSourceStack) { + super(commandSourceStack); + } + + /** + * {@inheritDoc} + * + * @return the source + */ + @Override + public @NonNull Entity source() { + return (Entity) super.source(); + } +} diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/GenericSource.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/GenericSource.java new file mode 100644 index 00000000..221a8637 --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/GenericSource.java @@ -0,0 +1,53 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.paper.util.sender; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.checkerframework.checker.nullness.qual.NonNull; + +@SuppressWarnings("UnstableApiUsage") +class GenericSource implements Source { + + private final CommandSourceStack commandSourceStack; + + GenericSource(final @NonNull CommandSourceStack commandSourceStack) { + this.commandSourceStack = commandSourceStack; + } + + @Override + public final @NonNull CommandSourceStack stack() { + return this.commandSourceStack; + } + + /** + * {@inheritDoc} + * + * @return the source + */ + @Override + public @NonNull CommandSender source() { + return this.commandSourceStack.getSender(); + } +} diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PaperSimpleSenderMapper.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PaperSimpleSenderMapper.java new file mode 100644 index 00000000..455ecd53 --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PaperSimpleSenderMapper.java @@ -0,0 +1,84 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.paper.util.sender; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.Command; +import org.incendo.cloud.SenderMapper; +import org.incendo.cloud.paper.PaperCommandManager; + +/** + * A simple {@link SenderMapper} implementation designed for use with {@link PaperCommandManager}. + * Allows for easily utilizing cloud's {@link Command.Builder#senderType(Class)} utilities despite the + * single {@link CommandSourceStack} implementation provided by Paper/Minecraft. + * + *

The {@link #map(CommandSourceStack)} implementation performs type dispatch based on the {@link CommandSourceStack#getSender() sender}, + * for example it will create a {@link PlayerSource} when {@link CommandSourceStack#getSender()} is a {@link Player}, and similar for + * {@link ConsoleSource} and {@link EntitySource}. Any other specific sender types do not currently have special handling + * and will fall back to a generic {@link Source} implementation.

+ */ +@SuppressWarnings("UnstableApiUsage") +public final class PaperSimpleSenderMapper implements SenderMapper { + + /** + * Create a new instance of {@link PaperSimpleSenderMapper}. + * + * @return a new instance of {@link PaperSimpleSenderMapper} + */ + public static @NonNull PaperSimpleSenderMapper simpleSenderMapper() { + return new PaperSimpleSenderMapper(); + } + + PaperSimpleSenderMapper() { + } + + @Override + public @NonNull Source map(final @NonNull CommandSourceStack base) { + CommandSender commandSender = base.getSender(); + + if (commandSender instanceof ConsoleCommandSender) { + return new ConsoleSource(base); + } + + if (commandSender instanceof Player) { + return new PlayerSource(base); + } + + if (commandSender instanceof Entity) { + return new EntitySource(base); + } + + return new GenericSource(base); + } + + @Override + public @NonNull CommandSourceStack reverse(final @NonNull Source mapped) { + return mapped.stack(); + } +} diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PlayerSource.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PlayerSource.java new file mode 100644 index 00000000..793177c0 --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/PlayerSource.java @@ -0,0 +1,45 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.paper.util.sender; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Specialized variant of {@link Source}, for when the {@link CommandSourceStack#getSender() sender} is a + * {@link Player}. + */ +@SuppressWarnings("UnstableApiUsage") +public final class PlayerSource extends EntitySource { + + PlayerSource(final CommandSourceStack commandSourceStack) { + super(commandSourceStack); + } + + @Override + public @NonNull Player source() { + return (Player) super.source(); + } +} diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/Source.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/Source.java new file mode 100644 index 00000000..8ab0b9f8 --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/Source.java @@ -0,0 +1,53 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.paper.util.sender; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * A simple wrapper around {@link CommandSourceStack}. + * + * @see PaperSimpleSenderMapper + */ +@SuppressWarnings("UnstableApiUsage") +public interface Source { + + /** + * Gets the {@link CommandSourceStack}. + * + * @return the command source stack + */ + @NonNull CommandSourceStack stack(); + + /** + * Gets the underlying {@link CommandSourceStack#getSender() sender} from the {@link #stack() source stack}. + * + *

Specific implementations may override this method with a more specific return type.

+ * + * @return the source + */ + @NonNull CommandSender source(); +} diff --git a/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/package-info.java b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/package-info.java new file mode 100644 index 00000000..63401c7e --- /dev/null +++ b/cloud-paper/src/main/java/org/incendo/cloud/paper/util/sender/package-info.java @@ -0,0 +1,5 @@ +/** + * Built in command sender {@link org.incendo.cloud.paper.util.sender.Source types} and + * {@link org.incendo.cloud.paper.util.sender.PaperSimpleSenderMapper mappings} for modern Paper. + */ +package org.incendo.cloud.paper.util.sender; diff --git a/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PaperPlugin.java b/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PaperPlugin.java index 3ac7fe68..e2061c3b 100644 --- a/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PaperPlugin.java +++ b/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PaperPlugin.java @@ -23,18 +23,17 @@ // package org.incendo.cloud.examples.paper; -import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.plugin.java.JavaPlugin; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; import org.incendo.cloud.paper.PaperCommandManager; +import org.incendo.cloud.paper.util.sender.Source; -@SuppressWarnings("UnstableApiUsage") @DefaultQualifier(NonNull.class) public final class PaperPlugin extends JavaPlugin { - private final PaperCommandManager.Bootstrapped commandManager; + private final PaperCommandManager.Bootstrapped commandManager; - public PaperPlugin(final PaperCommandManager.Bootstrapped commandManager) { + public PaperPlugin(final PaperCommandManager.Bootstrapped commandManager) { this.commandManager = commandManager; } diff --git a/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PluginBootstrap.java b/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PluginBootstrap.java index 53b0634e..175ab573 100644 --- a/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PluginBootstrap.java +++ b/examples/example-paper/src/main/java/org/incendo/cloud/examples/paper/PluginBootstrap.java @@ -23,15 +23,20 @@ // package org.incendo.cloud.examples.paper; -import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginProviderContext; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; import org.incendo.cloud.execution.ExecutionCoordinator; import org.incendo.cloud.paper.PaperCommandManager; +import org.incendo.cloud.paper.util.sender.ConsoleSource; +import org.incendo.cloud.paper.util.sender.PaperSimpleSenderMapper; +import org.incendo.cloud.paper.util.sender.PlayerSource; +import org.incendo.cloud.paper.util.sender.Source; import org.incendo.cloud.setting.ManagerSetting; import static org.incendo.cloud.parser.standard.StringParser.stringParser; @@ -39,12 +44,12 @@ @SuppressWarnings("UnstableApiUsage") @DefaultQualifier(NonNull.class) public final class PluginBootstrap implements io.papermc.paper.plugin.bootstrap.PluginBootstrap { - private PaperCommandManager.@MonotonicNonNull Bootstrapped commandManager; + private PaperCommandManager.@MonotonicNonNull Bootstrapped commandManager; @Override public void bootstrap(final BootstrapContext context) { - final PaperCommandManager.Bootstrapped mgr = - PaperCommandManager.builder() + final PaperCommandManager.Bootstrapped mgr = + PaperCommandManager.builder(PaperSimpleSenderMapper.simpleSenderMapper()) .executionCoordinator(ExecutionCoordinator.simpleCoordinator()) .buildBootstrapped(context); @@ -58,7 +63,7 @@ public void bootstrap(final BootstrapContext context) { final String name = ctx.get("name"); mgr.command( mgr.commandBuilder(name).handler(ctx1 -> { - ctx1.sender().getSender().sendMessage("HI"); + ctx1.sender().source().sendMessage("HI"); }) ); }) @@ -71,6 +76,22 @@ public void bootstrap(final BootstrapContext context) { mgr.deleteRootCommand(name); }) ); + mgr.command( + mgr.commandBuilder("player_command") + .senderType(PlayerSource.class) + .handler(ctx -> { + final Player player = ctx.sender().source(); + player.sendMessage("hello player!"); + }) + ); + mgr.command( + mgr.commandBuilder("console_command") + .senderType(ConsoleSource.class) + .handler(ctx -> { + final ConsoleCommandSender console = ctx.sender().source(); + console.sendMessage("hello console!"); + }) + ); } @Override